Jump to content
🛡️FORUMS ARE IN READ-ONLY MODE Read more... ×

mrcurry

Member
  • Content Count

    665
  • Joined

  • Last visited

  • Medals

Everything posted by mrcurry

  1. mrcurry

    Forum has died

    1. Just cause you don't hear about it doesn't mean nothing is happening. Speaking about the countermeasures would make it easier for an attacker, and keep posting "we're working on it" and you'll look even more foolish. 2. Well is there any urgency? While we are customers, at the end of the day it's just a game and any attacker(s) will eventually tire and/or run out of resources or BIS will figure out their infrastructure. The attackers want anger, outrage and attention, it's the currency in whatever scheme they're playing at. All I'm going to give them is patience. This the perfect moment to pickup one of those 0-hours-played games in your steam library.
  2. mrcurry

    Progressbar

    From a quick glance: private ["...", "_TotalSpawned", "_MaxAiTeams", "...", "", ""]; means your _TotalSpawned is local to your script and you are using it like a number, the name also implies a number. Numbers are passed by value which means the value of _TotalSpawned will never change unless you update it inside your loop.
  3. CfgFunctions are always available too all, preinit functions will be called automatically on all machines. You should avoid execution of code that may or may not exist on the other machine. Only execute that which you know exists As a side note: Just so you are aware, defining the final function variables on your own like that means you do not get all the features of the functions library, like compileFinal or pre-preinit definition. Here's a not so organised example how to get full functionality.
  4. Broadly speaking you can either use a shared data container like @pierremgi suggested, ( publicVariable or setVariable with broadcast: true ), he explained it so I won't. The other option is to implement server query and client response functions and use remoteExec to handle the comms. It's more complex but encapsulates the code well. To do this split the procedure into 3 parts: fnc_server_query_destination - Runs only on server. Does prep and remoteExecs function 2. on the client. fnc_client_select_destination_and_respond - Here the client takes over. This runs only on client with interface. This is where you use the previous trick with the "MapSingleClick" eventhandler to fetch the result. Then the client remoteExecs function 3. back onto the server. fnc_server_handle_response - The server takes over again and applies the changes i.e. makes the helo move and what not. The remoteExec calls in this solution need to be sent only between the machines involved, do not use 0 as target. That will not work as is, no. remoteExec is fire-and-forget so cannot return a value. I just want to clarify that there are two parts to the problem we're talking about: Getting the selected position from the eventhandler to the calling script on client's machine. Getting the selected position from the client to the server. 1. can be solved with the hashmap-trick or using setVariable on the player 2. can be solved with the server-client response pattern or using publicVariable or setVariable on the player with broadcast: true There are no right answers to which approach to take, choose whichever you feel you can pull off. If you need more examples just say which method you'd prefer.
  5. The command has local effect so run it only when leader player == player.
  6. So you're trying to pass data to/from the separate scopes while avoiding global vars? Use local variables in your "controller" script (the one which adds the eventhandler), pass the required values as the "arguments" parameter of addMissionEventhandler to have them available in the eventhandler's scope as _thisArgs If you need to return a value from the eventhandler you can try this, I'm 90% sure it maybe works... Edit: Tested it, it definitely works. In your controller script: _data = createHashMap; addMissionEventhandler [ "MapSingleClick", { _thisArgs params ["_returnData"]; _returnData set ["some key", "some value"]; //Return whatever you need }, [ _data] //Important ]; waitUntil { count _data > 0 }; systemChat "map clicked!"; Here's a complete example with comments showing a simple teleport feature demonstrating the technique where the event handler returns the position to the calling script appropriately. Ofc working with MP you need to think about the locality of your operations; server vs client, who does what, what is the command requirements (LA / LE / GA / GE). No code formatting cause lousy options on phone Edited on PC.
  7. mrcurry

    Trigger thislist

    While this is true it is a simplified truth and I think it's worth highlighting for future readers that triggers are actually a special kind of object. thisTrigger refers to the actual trigger object which in turn holds all info like area, rotation, activation type and conditions, accessible through the triggerX commands.
  8. Nice! Then you really don't need to worry about performance of compile Vs execVM at such an early stage, just get it working. 🙂 That said you can do rapid prototyping with CfgFunctions too. If you are still using VSCode you can setup a user snippet to quickly generate the CfgFunctions entry for use in a prototype mission, when you're done testing the resulting function file is ready to be dropped straight into a larger project with no changes. Tomato tomato and whatever floats the boat
  9. Could I just take this moment to strongly recommend using the Functions Library to define your scripts into proper Functions: Arma 3 Functions Library Automatic compilation before anything runs. Your code will always be available as a missionNamespace variable TAG_fnc_functionName. And yes the code only compiles once. It's a different workflow than just creating sqf files, but very easy to work with once you get it set up and can really help keeping things neat and organised.
  10. Nice! I'll just drop this link here: https://community.bistudio.com/wiki/getRoadInfo
  11. I'm surprised you see any noticeable effect at all cause this line should be throwing/logging a script error. Unary (single argument) commands like "group" take precedence. With implict brackets added your code would look like so: _group = (group _this) select 1; but what you want is: _group = group (_this select 1);
  12. mrcurry

    remoteExec addEventHandler

    @RobustcolorFrom the biki: So short answer is yes you need to add it to all pcs to cover all possible shooters
  13. mrcurry

    isNil forEach

    Neat! You know, you could just say that it's the users responsibility to verify that the trigger exists before it's defined like that... 😛 But incase you don't wanna go that route I'd go with requesting the variable name of the trigger or target as a string instead and then at the start of your loop where you validate the list read from missionNamespace to get the reference and update the input array with the correct value. Any code after won't know the difference. Example: Assume _inputArray contains the list to validate. { if( _x isEqualType "" ) then { if( isNil _x ) then { // It's not a valid variable name, either throw an error or handle it as regular string } else { // It's a valid variable, get the value private _val = missionNamespace getVariable _x; // Here you could do further validation that _val contains an expected value i.e. it's an Object. _x = _val; // set local ref for further validation in the loop _inputArray set [_forEachIndex, _val]; // set array ref for use later in the script }; }; // Handle _x == Object and _x == Number after } forEach _inputArray;
  14. mrcurry

    isNil forEach

    Now we're getting somewhere. The error message is quite clear. It's not your condition checking that's the problem. It errors on this line: [BLUFOR, [CSWR_spwnsBLU], CSWR_group_BLU_light, _form_BLU_2, _be_SAFE, [_move_ANY], [this_trigger_doesnt_exist]] call THY_fnc_CSWR_add_group; cause when you "set the trigger" you build an array like this: [this_trigger_doesnt_exist] This essentially does two operations in order: Read value from variable "this_trigger_doesnt_exist" Create an array and insert said reference in the first index. In step 1 if the variable is nil (undefined) you will be reading the value from an undefined location in memory. In essence you are asking "What's in the box?" and the game goes "What box?" and throws the error. You simply cannot do that directly. So what to do? That depends on what your requirement is. Do you know what the trigger will be named? Great. Just use getVariable to retrieve the value with a reasonable default e.g. objNull. Use isNull to verify the quality of the input. Is the trigger input by the user? Have the user input a string instead/as well and parse it, getVariable is your friend here too. Is the value set by another script? Prior to creating the array verify that the expected variable is actually defined using isNil "variable_name".
  15. mrcurry

    isNil forEach

    This is why describing the whole scenario from the get go is useful. There are many ways to skin a programmable cat. 🙂 Hmm, isNil "_x" should work... Try just checking if the value is undefined using: isNil { _x } as the condition. Just curly brackets and no stringification needed. If that fails I'm gonna have to boot up the game for some tests. If you're parsing "user input" to your function you can use param to retrieve the value instead like so: _x = _spwnDelayMethods param [_forEachIndex, objNull]; This way _x will fall back to objNull if its undefined. Put that at the start of your loop and you can just check isNull _x and do comparisons with isEqualX commands etc. Nice and clean.
  16. mrcurry

    isNil forEach

    Either: _array = ["this_trigger_doesnt_exist"]; { if( isNil _x ) then { // Trigger doesn't exist, do what you must } else { // Trigger exists, we can get the reference using: private _trigger = missionNamespace getVariable _x; }; } forEach _array; Or: _array = ["this_trigger_doesnt_exist"]; { private _trigger = missionNamespace getVariable [_x, objNull]; if( isNull _trigger ) then { // Trigger doesn't exist } else { // Trigger exists }; } forEach _array;
  17. Correct, the described behaviour is the main difference between reference types (arrays and hashmaps) and value types (scalars). This actually a pretty common feature in many languages and is not unique to SQF.
  18. This has nothing to do with profileNamespace specifically. This is cause you are setting the profileNamespace-variable "saveData" to the same data in memory as scoresArray points to. Remember: array variables are just reference holders to sequences of data. set updates the data inplace. In your second version your are creating a new array in memory using _tempArr = []; and then you essentially copy the data to it, hence the problem disappears. An example: a = [1]; // "[]" creates the array in memory and returns the address to it, then "a =" defines the variable "a" and assigns the address to it. b = a; // "b" now contains the same adress as "a", both variables point to the same data b pushback 2; // adds an element to the data, "a select 1" would return 2. Edit: Note that since profileNamespace is essentially a loaded copy of the contents of the profile-file on the harddrive you would still have to use saveProfilenamespace again after you update the scores to save the changes to harddrive.
  19. this should be doing nothing at best or throw an error at worst. Have you enabled -showScriptErrors on your A3 launcher / startup parameters?
  20. @scottb613https://community.bistudio.com/wiki/forgetTarget
  21. This depends entirely on the use case. If a uniform distribution is required, meaning all outcomes have equal chance to occur, you need a different approach. For a proper uniform random range use: _rand = _min + floor random (_max - _min); Above _max is exclusive and won't be included, if you need inclusive _max use: _rand = _min + floor random (_max - _min + 1); These are both guaranteed to never generate value below _min. It's ofc ok to precompute the brackets into a variable and use that as input to the random call.
  22. If this fixed the issue one of the logic tests in the previous conditions obviously failed. To know for sure you'd have test them individually and see which one returns false. I'd do that before attempting a further fix.
  23. I can think of two ways. Method 1: For each group of detecting side, command: groups playerSide Call command targets on the current group Use the result to create your marker Method 2: For each group of the detecting side Add an "EnemyDetected" event handler In the event handler add your marker If you need information on the enemy you can use _groupLeader targetKnowledge _target These methods doesn't include how you track markers, check if an object has a marker or delete markers that are no longer relevant. If you want it, here's how I'd solve that: Edit: Oops, just realized you wanted groups, but the logic should be easy to extend to manage detected groups instead of individual units. The key is to remember that AI doesn't see groups, they see units. Groups are just an abstract composition, so you have decide what it means to "create a marker on the group". Do you mark the group leader's position or the average position of all units in the group? Do you include units that aren't detected yet? Do you interpret clusters of units as s group or rely on the game's predetermined groups.
  24. My 2 cents: Tell the story you want to tell. Make the mission you want to play. If your goal is a specific narrative then a given character makes more sense. The vanilla and Laws of War campaigns are good examples of this. This requires some solid writing though and I would recommend running any script or story by a trusted friend or partner for feedback.
  25. I'm fairly sure that lobby slots are derived from the mission sqm, so No... but I also haven't tried. If someone has succeeded please do tell. In the meantime your best bet is to place playable units and move them into the correct seat as the player loads in (initPlayerLocal). You can hide it behind a loading screen if you wish, the player won't know the difference if you do it right.
×