Jump to content

ZaellixA

Member
  • Content Count

    235
  • Joined

  • Last visited

  • Medals

Everything posted by ZaellixA

  1. It's not like we have a lot of information here, but from what I have understood so far a possible, yet quite crude, solution could look like the following /* * _units: The units in the trigger (those you want to keep) * _triggers: The triggers you want to delete (all except the one triggered) */ // Get the parameters passed to the script params["_units", "_triggers"]; // Delete the triggers { deleteVehicle _x; } forEach _triggers; // Delete the units that are not in the trigger { deleteVehicle _x; } forEach (allUnits - _units); // Get the groups private _groups = []; { _groups pushBackUnique (group _x); } forEach _units; // Create the patrol tasks { [_x, getPos (leader _x), 500] call BIS_fnc_taskPatrol; } forEach _groups; And then inside each trigger, you could call the script like private _triggers = [trig1, trig2, trig3, trig4]; // Make an array with all triggers [thisList, _triggers - thisTrigger] execVM "theScriptAbove.sqf"; // Call the script I know this is a very bad scripted solution but I believe that at least points to a certain direction. Hope it helps somehow. Please keep in mind that there must be a whole bunch of better ways to do achieve what you want to do here so do spend some time refining the solution or improvise another better one. Additionally, note that the provided code is untested, so treat with caution. Don't hesitate to ask again if you encounter further issues.
  2. ZaellixA

    Terminating sqf with !alive Trigger

    You shouldn't apologize. This forum here is to help people and if you see some rather "overwhelming" posts pointing many "incorrect"/bad practices is to help in the long-run. As I said, the fact that ArmA scripting is not something many people would call coding or programming does not mean that we could not benefit from good programming practices (such as the informative variable naming, code structuring and a lot more). So, please take those points as an extra (not aksed-for but nonetheless a piece of) help with the sole purpose to help you avoid troubles in the future (some of them before you even encountering them). Glad it worked for you and hope to see you again around here (not because you'll have a problem but helping others too). Take care, have fun, stay safe and ArmA a lot.
  3. ZaellixA

    Terminating sqf with !alive Trigger

    Please do go ahead and do some searching. You can consult the BIKI about variables to see how they work if you are not familiar with the concept (or actually any programming textbook really). Additionally, do consult the BIKI on the syntax of the commands you use. For example (from the BIKI) terminate accepts a script handle as an argument and not a string like what you provide in the triggers. So you should do something like terminate thisx; // Terminate the executioner animation script terminate thisy; // Terminate the victim animation script Furthermore, the variable this is a "magic variable" that holds the boolean returned by the trigger's condition check (see BIKI for more info). You should avoid like hell the assignment to magic variables as well as creating ambiguous, or uninformative variable names. You could very well use the thisx and thisy variables but note that returning to the script (or mission) after a month (or even less) they will provide absolutely no information as to what they hold or what the purpose of their existence is. This is bad coding and it is very hard to be maintained by either you or someone else. You could do something like /* * Activation field of first trigger */ execAnimHandle = execVM "executioner.sqf"; vicAnimHandle = execVM "victim.sqf"; /* * Activation field of second trigger */ hostHandle = execVM "hostagesafe.sqf"; // If you don't need the handle you could something like: execVM "hostagesafe.sqf" terminate execAnimHandle; // Terminate the executioner animation script executioner switchMove ""; // Switch the move of the executioner to "nothing" (not sure this is needed but pierremgi has provided for it so I will assume it should be there) terminate vicAnimHandle; // Terminate the victim animation script victim switchMove ""; // Same as above Now the code is clearer, you (or anyone who tries to modify/maintain the code) will easily understand what each variable holds and you have minimised the chances of using or overwriting variables that contain something else (and maybe needed/used elsewhere or further below) like this. ================================================================================ EDIT ================================================================================ Regarding the "victim.sqf" not found, make sure you don't have any typos (either in the script where you call the file, or the name of the file is not written differently) and that said script is either in the same folder as the mission .sqm or you call it correctly. For example, if you have the scripts inside a folder named script then you should call them like execVM "scripts\victim.sqf"; Please let us know if you encounter more issues.
  4. ZaellixA

    Terminating sqf with !alive Trigger

    What pierremgi is trying to say here is that after you call execVM you get back a script handler (this is what the command execVM gives you back) and you keep that inside a variable (the thing on the left-hand side of the equal sign). You can name the variable whatever you want. Make sure you make so that it does not start with an underscore. So in the activation field of the trigger you run the animation scripts there should be something like (not necessarily identical since the names I give may not coincide with the ones you gave to the variables) the following execAnimHandle = [executioner] execVM "executionerAnimationScript.sqf"; // You call the script with the animation for the executioner vicAnimHandle = [victim] execVM "victimAnimationScript.sqf"; // You call the script with the animation for the "victim" Where executioner and victim are the names of the units that represent the executioner and the one to be executed respectively. They are set in the name field of the object in the editor and please keep in mind that you may have named them differently. Now, in your version, you may pass some more arguments to the execVM inside the preceding (square) brackets but this doesn't change something since what we are interested in here are the execAnimHandle and vicAnimHandle. Those are the script handlers you can use to prematurely terminate the scripts. So, in another trigger you make you can set the condition to !alive executioner; This will trigger as soon as the executioner dies and in the activation field you can run (copying pierremgi's code) terminate execAnimHandle; // Terminate the script so that animation will not be executed executioner switchMove ""; // Set the animation of the executioner to "nothing" I hope this clarifies things a bit. If this solution does not work for you, or you face more issues please let us know about it, providing some specifics about the different result you want to achieve or the problem that arised.
  5. ZaellixA

    Terminating sqf with !alive Trigger

    Exactly how do you execute/run the .sqf files? Please provide your complete solution in order for people to be able to provide corrections/improvements.
  6. ZaellixA

    New to scripting

    Maybe you should provide more information on the problem. We can't really know exactly what you want with what you have provided. Regarding the code you provided, it is not clear as to where exactly you have placed the dceTeleport = FALSE; but if you have placed it inside the init.sqf (and not ini.sqf) it will make this variable equal to false. If the mod you refer to makes use of it to disable some of its functionality is unknown to me, so I will assume that the mod maker has instructed you to do so, thus it is what you want to achieve. This approach makes the use of myscripft.sqf (should it be myscript.sqf?) obsolete 'cause there's no apparent need for it (unless you call it somehow, but it is still irrelevant to the question). On the other hand, if you have the code you provided inside the myscripft.sqf and assuming that this is what you want to execute, then you could execute your script inside the init.sqf like private _nil = [] execVM "myscripft.sqf"; or with a call [] call compile preprocessFileLineNumbers "myscripft.sqf"; If any of those does not suit your needs please feel free to ask again. Once more, if you provide more information it will be easier to provide a better solution.
  7. ZaellixA

    adding an action to an object

    As the rest of the people have said above, you should be a bit more precise on what you are trying to achieve. I will try to provide a random example based on my understanding of your question. In this example, you should place a tablet somewhere and create a small Tanoa hangar, the one with the two sliding doors. In my example, I named the tablet object tablet and the hangar structure hangar (no wayyyy :D). So you could do the following in order to make the two sliding doors animate based on an actions attached to the tablet. // Add open holdAction to the tablet [ tablet, // Object the action is attached to "Open hangar doors", // The title of the action "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_hack_ca.paa", // Idle icon shown on screen "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_hack_ca.paa", // Progress icon shown on screen "_this distance _target < 3", // Condition for the action to be shown "_this distance _target < 3", // Condition for the action to progress {}, // Code executed on action start, { // Code executed on every progress tick private _hangar = (_this select 3) select 0; // Get the hangar private _animPhase = _hangar animationSourcePhase "Door_2_Sound_Source"; // Get the current phase of the doors private _animToGo = 1/(_this select 4); // Get the animation phase to move to if(_animPhase <= _animToGo) then { // Check if door is already midway _hangar animateSource["Door_2_Sound_Source", _animToGo]; // Open left door _hangar animateSource["Door_3_Sound_Source", _animToGo]; // Open right door }; }, // End of code executed on every progress tick {}, // Code executed when action completed {}, // Code executed when action interrupted [hangar], // Arguments passed to the script as _this select 3 12, // Duration of action 0, // Priority false, // Remove completed false, // Show unconsious true /* Show on screen */] call BIS_fnc_holdActionAdd; // Add close holdAction to the tablet [ tablet, // Object the action is attached to "Close hangar doors", // The title of the action "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_hack_ca.paa", // Idle icon shown on screen "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_hack_ca.paa", // Progress icon shown on screen "_this distance _target < 3", // Condition for the action to be shown "_this distance _target < 3", // Condition for the action to progress {}, // Code executed on action start, { // Code executed on every progress tick private _hangar = (_this select 3) select 0; // Get the hangar private _animPhase = _hangar animationSourcePhase "Door_2_Sound_Source"; // Get the current phase of the doors private _animToGo = 1 - (1/(_this select 4)); // Get the animation phase to move to if(_animPhase >= _animToGo) then { // Check if door is already midway _hangar animateSource["Door_2_Sound_Source", _animToGo]; // Open left door _hangar animateSource["Door_3_Sound_Source", _animToGo]; // Open right door }; }, // End of code executed on every progress tick {}, // Code executed when action completed {}, // Code executed when action interrupted [hangar], // Arguments passed to the script as _this select 3 12, // Duration of action 0, // Priority false, // Remove completed false, // Show unconsious true /* Show on screen */] call BIS_fnc_holdActionAdd; Two actions are attached to the object, one to open the doors and the other to close the doors. You could possibly refine the code here and optimize a bit but I hope you do get the basic idea. One more thing to note here is that using addActions is not a great way to do things because the conditions are checked at (almost) every frame which can end up in a significant performance degradation if many addActions are used in a mission. You could possibly add a trigger which will be activated by the players, with an area about 5 metres around the object to which you attach the actions, and attach the actions when the trigger is triggered (:|). And when people leave the area, remove the actions. This way, you can set the trigger condition check to a rather low value and ease the burden on the CPU. Finally, please note that the above code is not tested and may contain syntactic and/or logical errors. Please test before use. Let us know if this helps you somehow or if you may have more questions and or issues. Have fun, stay safe and ArmA a lot 🙂.
  8. ZaellixA

    only pilots fly

    I am a bit late to reply, but I would strongly recommend the use of event handlers over triggers. This is solely for performance since triggers constantly check a condition at specified intervals, while event handlers are called only when an event takes place. L3TUC3 has provided a decent solution and the only thing I could possibly suggest on top of it is the use of variables to declare which unit is a pilot or not (this will work for both AI and players). For the AI you could do something like the following in the init.sqf. I will assume you have five pilot units and have named them with the convention "pilotX", where 'X' is a number from zero to the number of the pilots minus one. for private _i from 0 to 4 do { (call (compile ("pilot" + (str _i)))) setVariable["isPilot", true, true]; // Set the variable and make it public (not sure this is needed) }; For the players, you could either add the variable manually, check the Steam ID and add the variable to specific players, or add the variable inside the init field of the units like // Check if variable is already set because init field runs for every client joining if(!(this getVariable["isPilot", false]) then { this setVariable["isPilot", true, true]; }; After that, you could use the solution that L3TUC3 suggested with some changes as below (using and adapting L3TUC3's code) this addEventHandler ["GetIn", { private _spot = _this select 1; // The seat the unit got into private _unit = _this select 2; // The unit itself if (_spot == "driver" && !(_unit getVariable["isPilot", false])) then // If the unit got into the driver seat doesn't have the isPilot variable set to true { _unit action ["Eject", vehicle _unit]; // Eject the unit hint "You are not a Pilot!" // Show a hint }; }]; this addEventHandler ["SeatSwitched", { _vehicle = _this select 0; // The vehicle the seats were switched in _unit1 = _this select 1; // The unit initiating the switching _unit2 = _this select 2; // The unit that got switched (if not an emty seat) _spot1 = assignedVehicleRole _unit1; // The new seat for unit 1 _spot2 = assignedVehicleRole _unit2; // The new seat for unit 2 if (_spot1 == "driver" && !(_unit1 getVariable["isPilot", false])) then { _unit1 action ["Eject", _vehicle]; }; if (_spot2 == "driver" && !(_unit2 getVariable["isPilot", false])) then { _unit2 action ["Eject", _vehicle]; }; }]; In essence, I have just removed the arrays with the pilots and have changed the checks inside the if statements to get the variables of the units (if not set, false is returned). I hope this helps somehow. If not, or if you have more questions please don't hesitate to ask :).
  9. Yep, this should work fine, but it's a wee bit more difficult to control the exact time the unit will appear and disappear.
  10. You could possibly do something like the following while {true} do { private _hour = floor daytime; // Get the hour of the local in-game time private _sheep = objNull; // Initialise the sheep if(_hour > 6 && {_hour < 21} && {_sheep isEqualTo objNull}) then { _sheep = createVehicle["Sheep_random_F", getPos player, [], 10, "NONE"]; // Create a sheep }; if({_hour < 6 || {_hour > 21}} && {!(_sheep isEqualTo objNull)}) then { deleteVehicle _sheep; // Delete the sheep }; // Sleep a while to save some CPU sleep 30; }; I am sure you could refine and make the code better in many ways, but I hope you do get the basic idea. Please let us know if you have any more issues or further questions. Have fun, stay safe and ArmA a lot.
  11. You don't really need to assign the global variable to a local in order to pass it to the setVariable command. You can do it like in the second example in my post above pierremgi's. I am not familiar with CBA's event handlers so I am not sure I understand correctly when and/or how often this event handler is triggered. I would suggest you try out pierremgi's solution too because if the event handler is running often then you won't really get any benefit from creating an event handler instead of using a sleep command in your code. I understand that for some reason this solution didn't work out for you. If you would like to test it a wee bit more let us know to help you out finding the root of the error. Nevertheless, since this works for you it's fine. Also, I hope you know better than me how CBA's event handlers work to have made this choice for your implementation. Have fun, stay healthy and ArmA a lot.
  12. Well, wherever you set the guys names and group names all you have to do is use setVariable. I will provide an example where I magically get those two units and I will assume that you have a way to get access to them. So, the example would look like private _bluGuy = theBlueGuy; // The name on the right is the name you will give the unit in the editor missionNamespace setVariable["bluGrp", group _bluGuy, true]; // Set the group of the bluefor guy as a public variable privaet _civGuy = theCivGuy; // The name on the right is the name you will give the unit in the editor missionNamespace setVariable["civGrp", group _civGuy, true]; // Set the group of the civilian as a public variable Alternatively, you could skip private variables and go directly for the setVariable command like missionNamespace setVariable["bluGrp", group theBlueGuy, true]; // Set the group of the bluefor guy as a public variable missionNamespace setVariable["civGrp", group tehCivGuy, true]; // Set the group of the civilian as a public variable Hope this helps somehow.
  13. EDIT: I apologise in advance for the long post. It contains many examples which could possibly be shortened but I decided to leave them as is. Hey, I found some time to improvise on a possible solution with the commands mentioned above. I want to stress again the fact that I haven't used any of the commands I suggest here, so all code presented is based on the BIKI pages and the intended use of the commands, as they are presented in their explanation/example pages. So, please treat the code with caution and if unsure assume it is not working as intended (this means... test, test and test again). Before starting, I would like to mention a couple of things about the code. I will use some variables which I assume you will have available in your code. Such variables are the soldier whose knowledge about other units you want to check. So, starting with targetKnowledge, a possible solution to your problem would be // private _soldier: The unit whose knowledge to check // Get the _soldier's side to use below (to avoid constantly calling the command) private _soldSide = side _soldier; // Run forever... for testing only while{true} do { { private _trgInfo = _soldier targetKnowledge _x; // Get the knowledge of the target if(!((_trgInfo select 4) isEqualTo _soldSide)) then { // Check if the unit is NOT in the same faction with the _soldier systemChat (str (_trgInfo select 1)); // Print whether the unit is known to the _soldier }; } forEach (allUnits - _soldier); // Check against all units but the _soldier // Sleep a bit to save some CPU sleep 5; }; Of course, you can refrain from using forEach (which can be quite CPU intensive) if you know exactly against who you would like to check. For example, if you have the _soldier mentioned above and you also have the name of the unit to check against you could do something like // private _soldier: The unit whose knowledge to check // private _unit: The unit to check against // Run forever... For testing only while{true} do { private _trgInfo = _soldier targetKnowledge _unit; // Get the knowledge of the target systemChat (str (_trgInfo select 1)); // Print whether the _unit is known to the _soldier // Sleep to save some CPU sleep 5; }; Next command is nearTargets. You could possibly use it to get whether one unit is recognised by the enemy or not. I am not sure how this is calculated so it may or may not be useful to you. An example could look like // private _soldier: The unit whose knowledge to check // Get the _soldier's side to use below (to avoid constantly calling the command) private _soldSide = side _soldier; // Run forever... for testing only while{true} do { private _targets = _soldier nearTargets viewDistance; // Get all targets that are up to the view distance { // Check the subjective cost which is positive for enemies if((_x select 3) > 0} then { systemChat format["Enemy soldier found at coordinates: %1", _targets select 0]; // Inform of enemy's location }; } forEach _targets; // Sleep a bit to save some CPU sleep 5; }; Alternatively, you could one-line the forEach command like (not a big fan of it but it's up to you to decide) // private _soldier: The unit whose knowledge to check // Get the _soldier's side to use below (to avoid constantly calling the command) private _soldSide = side _soldier; // Run forever... for testing only while{true} do { { // Check the subjective cost which is positive for enemies if((_x select 3) > 0} then { systemChat format["Enemy soldier found at coordinates: %1", _targets select 0]; // Inform of enemy's location }; } forEach (_soldier nearTargets viewDistance); // Go through all targets that are up to the view distance // Sleep a bit to save some CPU sleep 5; }; From what I found on BIKI, the big drawback with this command is that you may get inaccurate information, as what is returned is what the unit knows. Now, this may be closer to what you want since you say that you would like to understand how and/or when an AI unit gets knowledge of other units. Additionally, this command does not allow to check only one unit so you'll have to do something like the following if you want to check only one unit // private _soldier: The unit whose knowledge to check // private _unit: The unit to check against // Run forever... For testing only while{true} do { private _targets = _soldier nearTargets viewDistance; // Get the targets up to the view distance private _unitIdx = _targets findIf{(_x select 0) inArea [getPos _unit, 2.5, 2.5, 0, false]}; // Find the unit you are interested in // Check if perceived position is in area // of a circle with 5 metres diameter around // the actual position of the unit. If this is // true then this is the unit you want if(_unitIdx != -1) then { systemChat "Unit found!"; }; // Sleep to save some CPU sleep 5; }; Now, at least to my eyes, this is "not very nice" (awful is the right word to use here). I am not sure whether this check is more efficient than going through all the targets. Alternatively, you could filter out the enemies first and then perform this test (omitting the comments to make it more readable) // private _soldier: The unit whose knowledge to check // private _unit: The unit to check against // Run forever... For testing only while{true} do { private _enemies = _soldier nearTargets viewDistance; // Get the targets up to the view distance _enemies = _enemies select {(_x select 3) > 0}; // Use the same array for convenience and get the enemies only private _unitIdx = _enemies findIf{(_x select 0) inArea [getPos _unit, 2.5, 2.5, 0, false]}; // Find the unit you are interested in if(_unitIdx != -1) then { systemChat "Unit found!"; }; // Sleep to save some CPU sleep 5; }; =================================================================== EDIT: After having another look, this second implementation, most probably, is slower than the first since you have to traverse the array twice. Haven't checked so I can't really say, but it seems like that to me. =================================================================== Or, in the two solutions above you could possibly get the index of the unit and use it to extract more information about the unit (from the _enemies array). Finally, I found another command, targetsQuery, which could possibly be of help here. The advantage of this command is that it also returns the units as objects which you could possibly use somehow. So a solution with this command could look like // private _soldier: The unit whose knowledge to check // Get the side of the unit to avoid constantly calling the command private _soldSide = side _soldier; // Run forever... for testing only while{true} do { private _knownUnits = _soldier targetsQuery[objNull, sideUnknown, "", [], 0]; // Get all known units { if(!((_x select 2) isEqualTo _soldSide)) then { systemChat format["Enemy soldier is found at coordinates (2D): %1, _x select 4]; }; } forEach _knownUnits; // Go through all the known units // Sleep a bit to save some CPU sleep 5; }; As before, you could possibly one-line the array in forEach command like // private _soldier: The unit whose knowledge to check // Get the side of the unit to avoid constantly calling the command private _soldSide = side _soldier; // Run forever... for testing only while{true} do { { if(!((_x select 2) isEqualTo _soldSide)) then { systemChat format["Enemy soldier is found at coordinates (2D): %1, _x select 4]; }; } forEach (_soldier targetsQuery[objNull, sideUnknown, "", [], 0]); // Go through all the known units // Sleep a bit to save some CPU sleep 5; }; Alternatively (and possibly a bit more efficiently), you could filter the units returned by the command if you know the side you are interested in. This would look like (with the one-lined example) // private _soldier: The unit whose knowledge to check // Run forever... for testing only while{true} do { { systemChat format["Enemy soldier is found at coordinates (2D): %1, _x select 4]; } forEach (_soldier targetsQuery[objNull, west, "", [], 0]); // Go through all known units of west (BLUFOR) side // Sleep a bit to save some CPU sleep 5; }; Of course, if you want exactly one unit you could go by (again with the one-lined example) // private _soldier: The unit whose knowledge to check // private _unit: The unit to check against // Run forever... for testing only while{true} do { private _knownUnits = _soldier targetsQuery[objNull, west, "", getPos _unit, 0]; // Get west units 200m around the _unit private _unitIdx = _knownUnits findIf{_x isEqualTo _unit}; if(_unitIdx != -1) then { systemChat "Unit found!"; }; // Sleep a bit to save some CPU sleep 5; }; I just ran out of examples here 😂. Nevertheless, please note again that those snippets may produce a whole bunch of errors, may not work as intended, may not be useful to you and may have a whole lot more of issues (if, for example, I misunderstood their use or even the locality of theri arguments etc.). So, go ahead and test, test and test some more. Hopefully, you will be able to see in advance which commands and which examples may be useful to you and in what way. This will save a lot of time from testing and trying out commands. If you manage to find a good solution to your problem, please take some time to post it here for the benefit of other users. Finally, if you find yourself in need of more help do not hesitate to post here again with your problem. Have fun, stay safe and ArmA a lot.
  14. To be honest, I haven't used it before so I can't really know anything about possible limitations, but from the BIKI it seems that you could possibly use targetKnowledge or even nearTargets. I don't have the ability to test the commands now so I can't really provide too much help here except some speculative implemetations. I don't have too much time at the moment so I'll try to fix something with those commands when I find some time. Please let us know if any of those worked out for you and if possible provide your solution for other people who might have the same or similar issues.
  15. Like Schatten suggested, the problem should be that you use variables that are not existent in the scope of the event handler. Most probably you should make the variables global, or in case you intend to use the handler in MP public either with publicVariable command or with setVariable command with the last argument set to true. An example with the latter could be // Get the group of the player (consider it to be the group you want) private _bluGrp = group player; // Set a variable with the group in mission namespace and broadcast it to be public missionNamespace setVariable["blueGroup", _bluGrp, true]; Then, you could get the group inside the event handler like // Inside the event handler private _bluGrp = missionNamespace getVariable ["blueGroup", grpNull]; // Get the group // Check if the group exists (you can skip this test if you are sure the group exists) if(isNull _bluGrp) exitWith { systemChat "Group is empty"; } // Make the player join the group player joinSilent _bluGrp; // Rebroadcast the group to be available to other clients too missionNamespace setVariable["blueGroup", _bluGrp, true]; The same approach would work for the civilian group but you should either create it or get it from a civilian or whatever suits your needs best (I assume you already have that since it is present in the code you submitted). Please let us know if that works for you or if you would require further help with it.
  16. It seems that you have created a variable that is not used. _next is intialised to an empty array but it is not used subsequently. Unless of course, you use it at some other place futher down that you haven't shown here.
  17. An example would be something like the following (copying JohnKalo's solution) // Check if any of the units inside the trigger area is in player's group thisList findIf {_x in (units (group player))} != -1; Hope this helps somehow. Let us know if it doesn't or you would like it implemented differently
  18. Can't you use any player present at the condition of activation? Unless of course, you have players in more than one sides. In this case, you should put in the condition something like // Check if a player of specific side is inside the trigger thisList findIf {isPlayer _x && {(side _x) isEqualTo west}} != -1; // Change west to match the side you wish to check for
  19. Larrow's solution seems quite generic (I personally consider this to be something good) and, most probably, works for most (if not all) situations. One possible tweak (one I always struggle for) is to change count to findIf, which will terminate as soon as the condition returns true, so you won't have to go through the whole array every time. This could look like (showing only the waitUntil part) waitUntil { _mines findIf {mineActive _x;} == -1; }; Now, especially if you don't have many mines in this minefield of yours, the benefit from this change could be negligible (haven't performed any tests and I don't have any idea as to how CPU intense mineActive command is). Nevertheless, I do believe it's a good habit to try and optimise the code if you can, especially if the syntax is not affected (a lot). One more thing to add would be a sleep command in order to save some CPU cycles. Checking (almost) every frame doesn't provide much of a functionality improvement while using CPU for no good reason (in my opinion of course). This could look like waitUntil { sleep 5; // Tweak value to meet your requirements _mines findIf {mineActive _x;} == -1; }; Apart from those two, I believe that Larrow's response should be fine. Well, I think it's already fine, but I do believe you could benefit a wee bit from those two small changes, especially from the second one (sleep command). Hope this helped at least a wee bit. Have fun and ArmA a lot.
  20. Glad you got a nice answer here (personally I am a big fan of findIf and I have a feeling that it is ALWAYS the right command to use :D:P). Feel free to throw any question you may have if you find yourself stuck with this or any other command. Have fun and ArmA a lot 🙂.
  21. @Von Quest, from the linked page it seems that reloadSpeed is also linked to the speed with which a unit changes its weapon. I believe that this is constant time, but I am not sure about it. So, this leads me to think that maybe reloadSpeed is linked to how fast the AI will decide to do one of the two actions (reload and change weapon). I can't be sure about it, but it is a nice new test for me to run :). I'll make sure to post here again if I get any "robust" results. One thought though is if the reloadSpeed is a factor imposed on the "magazineReloadTime". Just a thought though... As I said, if I get any results I'll let you guys know...
  22. ZaellixA

    Switch/While loop check

    @Leon Harrington, you should try Larrow's solution. I haven't tested personally, but it seems quite legit and I can't spot any errors (at least syntactical) by eye inspection.
  23. @TheoneandonlyNOR believe me when I say that these balancing issues are quite minor compared to structuring and coding the whole conversion (as wogz187 called it). There are many games and/or mods (Elite mod for Warhammer 40K Dawn of War 2 is a very good example) that constantly tweak their balancing. It is quite hard to find the "absolute balance" for a game/mode but I strongly believe that this is something you should consider in a later stage of the development. As wogz187 said, we'll be here to help in the best of our ability, so please don't hesitate to contact us again at any stage of the development. And to conclude this short post of mine, even if you never manage to finish this project, I am sure there's a whole lot of knowledge and other hard and soft skills to get from giving a try. I will surely be around to see it happening 🙂!
  24. Your project is really ambitious, especially for someone who does not know how to script. I definitely don't mean to discourage you here, as I really believe that one should have ambition in order to do something good. My suggestion is to follow a divide-and-conquer approach here. In my opinion, the most important part of your project should be planning. You should plan the interaction of each part of the project with the rest, if this is needed, and set clear and concise requirements for each of the parts/systems of the project. This is not something easy, but I believe that if you manage to do that the implementation of each sub-system/part of the project will become easier and in many cases, different sub-systems could be implemented in parallel (if they don't depend on each other or interact with other systems). I will PM you for more chit-chat, but I really believe that you should grab a pencil and a lot of paper sheets and start drafting! I hope more (and more experienced than me) people will contribute here. Feel free to post again, or PM if you need further assistant or wanna chat more about it (prefer PM for the latter).
  25. I can't see something wrong with what you got. I only changed the spawn to call because in the main body of the function there's no sleep (or other "delay") command, so there's no actual reason to give the whole function to the scheduler, you can just execute it. Obviously, inside the function, you do give some code to the scheduler with spawn but this has nothing to do with the execution of the function. The function actually just gets the parameters and passes them to the code that is given to the scheduler. Thus, no sleeps in the function, so no need to spawn instead of call. So, I thought it would be better not to clutter the scheduler with scripts. Of course one could omit entirely the creation of a function and just do something like /* * Script file called surrender.sqf */ // Get parameters params [["_grp", grpNull, [grpNull]]]; // Get the group (added valid types) // Pass code to the scheduler [_grp] spawn { private _grpUnits = units (_this select 0); // Get the units directly // Wait until the group flees waitUntil { sleep 1; // Sleep to save some CPU fleeing (_grpUnits select 0); // Check only one of the units // because the whole group flees as a whole or none at all }; { _x setVariable ["you_surrender", true]; // Keep this variable if you want [_x] call You_fnc_surrender; // Make the unit surrender } forEach _grpUnits; }; And then just call the script like [group this] call compile preprocessFileLineNumbers "surrender.sqf"; Although, using compile preprocessFileLineNumbers is not the best idea ever. So you could change the script a little bit like /* * Script file called surrender.sqf */ // Get parameters params [["_grp", grpNull, [grpNull]]]; // Get the group (added valid types) private _grpUnits = units _grp; // Get the units // Wait until the group flees waitUntil { sleep 1; // Sleep to save some CPU fleeing (_grpUnits select 0); // Check only one of the units // because the whole group flees as a whole or none at all }; { _x setVariable ["you_surrender", true]; // Keep this variable if you want [_x] call You_fnc_surrender; // Make the unit surrender } forEach _grpUnits; and instead of calling the script that will just get the parameter and then just pass it to the code that the scheduler will handle, you can give the script directly to the scheduler. The only overhead imposed to the scheduler here is to get the parameter and create the local variable to hold it. I am not sure how much this is for ArmA but I would be it is nothing compared to the rest of the script commands. So with the above script, you should call it like [group this] execVM "surrender.sqf"; Please, keep in mind that I have NOT tested any of those scripts so I cannot guarantee that they work. Additionally, I haven't performed any performance tests, so I cannot say whether one or the other way of calling and/or structuring the code is more efficient and in what way than the other. I would be glad to hear your opinions and results on any of those topics. Happy ArmA :).
×