Jump to content


  • Content Count

  • Joined

  • Last visited

  • Medals

Community Reputation

379 Excellent


About ZaellixA

  • Rank
    Staff Sergeant

Contact Methods

  • Skype
  • Biography
    Born in Ioannina, Greece. Grew up all around Greece and now still trying to settle somewhere. Sound engineering pays for most of my expenses.
  • Steam url id
  • Linkedin
  • Reddit

Profile Information

  • Gender
  • Location
  • Interests
    Acoustics, Digital Signal Processing, ArmA 3, Programming, Research, Computational Acoustics, Wave-Fields, 3D Audio, Electroacoustics

Recent Profile Visitors

1774 profile views
  1. Thanks for the post. I do know that but due to the fact that some people use it one way and the other, it is not very clear which is the case here or even if in this case the meaning is somewhat different. To be honest I strongly believe that in this context acceleration and deceleration are indeed the same thing (dependent only on the sign) I do my best to avoid passing down information based on mere speculations. This is the sole reason I wanted to clarify that to me it is not very clear in the current context. Thanks for the clarification though :).
  2. What I suggested does not allow for trajectory prediction, it is just a way to calculate the air friction and the "alternative solution" allows to graph the air friction against time (or even distance/displacement since those two are related through speed). I'll try to explain a bit better in case this could indeed provide some help. Unless I'm utterly mistaken, all we can do is consider that the bullet will be "ejected" at the time you click your mouse button (or whatever way you use to shoot a gun). This means that for time t = 0, the velocity of the projectile (bullet) will match the initial, or muzzle, velocity provided by its config file (I believe this is where this value is set but I am sure you know that better than I do). The simplest case of all, and then one that is implied to be used by BI in the web page you cited, is to assume that the air friction is constant for each projectile. In this case you could use the formula you provided to calculate the air friction. I replicate it for completeness. airFriction = deceleration/(velocity^2) Now, you do have the velocity but you don't have a value for the deceleration. One, simple, way to acquire it is to get the velocity of the projectile in another time instance, with t = t2. If the air friction is indeed a constant, then t2 can be any instant after the initial ejection of the projectile but before it hits any object (you want air friction to be the only external force applied for the formula to be valid). An example could be to get the velocity of the projectile 1 millisecond after it is ejected. This could be done in script like // Add an event handler to trigger when the user fires a weapon player addEventHandler["FiredMan", { private _projectile = _this select 6; // Get the projectile [_projectile] spawn { private _bullet = _this select 0; // Get the bullet into this script private _initVel = vectorMagnitude (velocity _bullet); // Get its initial velocity at this moment sleep 0.001; // Sleep for 1 millisecond private _finalVel = vectorMagnitude (velocity _bullet); // Get the bullet's "new" velocity // Assuming deceleration is negative acceleration, it is calculated as the difference in speed in // two time instances over the time interval during which the change happened private _deceleration = (_finalVel - _initVel)/0.001; // Calculate the deceleration as the difference of the two velocities over the time interval // Print the results systemChat ("Deceleration of the bullet is: " + str(_deceleration)); // Print the deceleration systemChat ("Air friction of the bullet is: " + str(_deceleration/(_finalVel^2))); // Print the air friction calculated with the given formula }; }]; Now, there's a couple of details to be taken into account here. First and foremost is the use of sleep. Personally, I am not sure whether this delay/sleep is accurate or even steady (to my limited knowledge, in programming, a steady clock is one that for later instances, it is guaranteed that will provide a greater value compared to the initial one). It is up to the scheduler to take care of the delays and sleeps which may render the whole process inaccurate. I believe that by running the "simulation" many times and averaging could provide a better estimate (not necessarily unbiased though, especially if the actual sleep duration is always equal or greater to the specified - this could add a negative bias to the time interval if I am not mistaken). I am sure there's people in the forums that could potentially provide more insight into this. Nevertheless, I believe this is a well educated mathematical formulation to get an estimate of the deceleration and in extend the air friction. Second point to make is that I am not sure (it is not very clear to me) whether deceleration is indeed negative acceleration, in which case its calculation (or its estimate at least) should be correct in the script, or just the difference between the value of speed between two time intervals, in which case the calculation is not correct and the actual value will depend on the time interval (which makes it a weird way to calculate the value at minimum). Third, as mentioned in my previous post, is that I am not sure how BI calculates the velocity. Most probably, it should be the magnitude of the (3D) velocity of the body, in which case, again, the calculation above should be correct. Alternatively, BI could use only the y component of the velocity to calculate air friction, thus ignoring effects such as gravity. Nevertheless, this would also seem weird to me, as it would then depend on the direction the muzzle is pointed. In reality, one would have to calculate the change in velocity at the direction of the initial muzzle direction in order to acquire a more accurate speed (in one direction) estimate. This requires dot products with the directional (unit for convenience) vector pointing towards the direction the muzzle is pointing. Not sure how big a difference this could make, especially for very short time intervals though. I do hope this helps somehow, although I really doubt that this way of estimating the air friction renders itself for "offline" calculations (which I believe is what you really want to achieve). Additionally, as sarogahtyp mentioned, they already have a (quite complex I assume ) script which could potentially provide more help (and hopefully they put much more thought into it and found better ways to get the results you seek). As a final remark, please note that the presented script is not tested and should be treated with caution.
  3. I believe the situation here is simpler that it looks. The best idea would be to use the given formula to estimate the air friction (which I am not sure it equals the drag, but this is for a different topic). My best bet would be to use a linear approximation which means that you should do exactly as you described above. Replicating here: According to the web page you cited, it seems that BI does indeed use a linear approximation for the deceleration, which in turn ends up being a linear approximation to the air friction, making it a constant stated by the slope of the deceleration-vs-squared velocity plot. Now, assuming a linear trend, you could peak any portion of the trajectory to estimate the air friction, since it is given by the slope, which is a constant. Thus, although your assumption that you should use the final velocity to be 0 is not incorrect, it does not render itself to performing actual calculations (you would have to use calculus to get past it and I don't think it is implemented in ArmA 3 scripting). On the contrary, as mentioned above, you could use another portion of the bullet flight-time to estimate the air friction with the formula you provided yourself. An example would be to measure the velocity at, say 0.5 seconds after it was fired and use those values to do the estimation. This would be something like // Assuming some given values here for the demo private _initVel = 850; // Initial/muzzle velocity of 850 m/s private _finalVel = 732.4; // Measured velocity after 0.5 seconds equal to 732.4 m/s private _timeOfFlight = 0.5; // Time of flight of the bullet at the moment of the velocity measurement private _deceleration = (_finalVel - _initVel)/_timeOfFlight; // Calculate deceleration private _ airFriction = _deceleration/(_finalVel * finalVel); // Use BI's given formula Alternative approach If would like to verify the assumption that the air friction is a constant given by the slope of the graph of deceleration versus the squared velocity you could get the velocity at different time instances (a regularly spaced grid would be the easiest way) and create a graph of the deceleration versus the square of the velocity. From that you could estimate the slope, or even better, calculate the slope, or even directly the air friction for each grid point (well actually the midpoint between grid points). This could possibly look something like the following // Get the object private _obj = ; // Get the bullet here somehow // Assuming some constants for the demo private _initVel = 850; private _dt = 0.01; // The time-grid spacing (for regular grid) private _airFriction = []; // Create an array to hold the calculated air friction // Calculate 100 times for "_idx" from 0 to 99 do { sleep dt; // Wait for duration dt private _speed = speed _obj; // Get the speed of the object at this instant in time private _dV = _initVel - _speed; // The difference in speed between the two time steps -> the deceleration _airFriction pushBack (_dV/speed); // Calculate the air friction at this iteration and put it in our results array _initVel = _speed; // Update the speed to use in the next iteration }; At the end of this snippet you will get (the linear approximation of) the air friction at times corresponding to the midpoints between the time grid points. One note to make here is that I am not sure whether you should use the command speed, which, according to BIKI, gives the y component of the velocity of the object, or calculate the magnitude of the velocity and use that instead. The magnitude could be calculated as private _vel = velocity _obj; // I assume you already have something in _obj // Manual calculation (not optimal) private _velMag = sqrt((_vel select 0)^2 + (_vel select 1)^2 + (_vel select 2)^2); // Manually calculate the magnitude // With built-in command private _velMagBest = vectorMagnitude (velocity _obj); // It is always advised to use built-in commands
  4. I'll agree with @Harzach here. Encouraging someone to find a solution doesn't seem like a step (first or not) towards a solution. Nevertheless, I just wanted to make a point that, in my opinion, it would be quite instructive to post when we have something to add to the knowledge base of the community in some way. Not much to be done about it, if this is the case. I am sure we've all seen people posting once or twice and then abandoning their question (for various reasons) and others that insisted "until the end" in an attempt to solve their problem at hand. All we can do is provide educated and well structured solutions and suggestions to the people here in order to increase the overall level in the community and help people. I don't think (just my opinion though) that scripting and modding is necessarily, directly, related to playing the game. I had been playing ArmA for quite some time (about 5 to 6 years) prior to start scripting. I haven't really put much research effort in finding out if this is the case so it may be otherwise.
  5. Although I understand that interacting with people can manytimes provide insights and instigate discussion and provide new solutions, I am not sure how helpful a comment like "I don't know" is... There's but a minuscule portion of the forum users who can say the opposite for the majority of the topics here. So, I believe that posting to say you don't know how to do something and/or you cannot provide the solution is not very helpful to the OP.
  6. I believe @Ibragim A has provided a nice solution. I would alter it just a bit to incorporate a small change. The changed version would look like (reusing the code provided by Ibragim A) _units = allUnits; // As an example { // For each _x addEventHandler ["FiredMan", { // Event handler code params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle"]; // Here is your block called on every fired shot: // HERE I CHECK WHETHER THE TRIGGER IS "ALIVE" SEPARATELY if (!alive _trg_1) exitWith {_unit removeEventHandler [_thisEvent, _thisEventHandler]}; // If the trigger is not "alive" remove the event handler completely if (_weapon in ["Throw","Put"]) exitWith {}; // Will not continue, if unit throws some grenade or put an explosive or trigger is deleted if (_unit inArea trg_1) then { // Here is your block called in case _unit fired while in area of trg_1 call Your_script.sqf // As an example deleteVehicle trg_1; // If you do not need to call Your_script.sqf on every shot // REMOVE THE EVENT HANDLER IF YOU DELETE THE TRIGGER _unit removeEventHandler [_thisEvent, _thisEventHandler]; } }]; } forEach _units; So, the actual change is that I remove the event handler if the trigger is deleted. I do that for the unit which calls the deletion of the trigger right after the deletion of the trigger, which of course should be deleted along with the deletion line if you don't intend to delete the trigger or do it in another place outside the event handler. For the rest of the units I added a separate check (Ibragim A was already checking for it in order to skip the event handler's execution, so I just moved the check into a separate check) on the top of the code to be executed by the event handler to test whether the trigger exists or not and if not the event handler terminates and its removal is called. Of course, these changes are relevant (as well as Ibragim A's check for the status (alive/dead) of the trigger) if you intend to delete the trigger some time or make the code more generic. I hope this provides an alternative, improvement or at least some insight. Have fun with ArmA.
  7. Hey Jujurat, like the rest of the people here I would like to congratulate you for your extremely good work on this map (although I haven't experienced it in the game yet). It looks very very nice in all of the pics and vids. Just one request... Stop posting so much content 'cause you're getting us all "wet" ;P. No, just kidding (well you do get us "wet") keep sending more content towards the community and I'm sure you'll get back nice feedback (like ANZACSAS Steven provided). A great round of applause to you and huge appreciation for sharing your time and work with the community!
  8. Holy f***ing sh*t...!!! This looks absolutely astonishing...!!! I haven't played ArmA 3 for quite some time now but I'll definitely give this map a go when it's ready...!!! And by the way, please go ahead and post WIP stuff next time you decide to do something similar...!!!
  9. But, when and how are you gonna check? Is a reload guaranteed when the magazine goes empty, 'cause in this case this could very well be used in the FiredMan event handler shown above. Otherwise I can't really see an easy way to use it apart from constantly checking if the unit is reloading. Do you have something specific in mind???
  10. I assume you use your code in either initPlayerLocal.sqf if in multiplayer or init.sqf if in single player. Instead of having the loop running "indefinitely" (as long as the player is alive of course), you could spawn the code from the WeaponAssembled event handler. You could also save the script handler to a variable in some namespace and then terminate it in the WeaponDisassembled event handler. This way, your while-loop would be running only when the UAV is assembled. This could look like (reusing your code and denoting with comments what has been changed) player addEventHandler ["WeaponAssembled", { params ["_unit", "_staticWeapon"]; _unit connectterminaltoUAV _staticWeapon; _staticWeapon engineOn true; _staticWeapon setCaptive true; player action ["SwitchToUAVGunner", getConnectedUAV player]; _grp = group _staticWeapon; _wp = _grp addWaypoint [getMarkerPos "markerUAV", 0]; _wp setWaypointType "MOVE"; _staticWeapon flyInHeight 200; /* * HERE YOU SPAWN THE CODE THAT CHECKS FOR THE UNITS FOUND IN THE TRIGGER AREA * AND GET THE HANDLER OF THE SCRIPT */ private _scriptH = spawn [ while {alive player} do { if (((units east) inAreaArray triggerAllSpotted) findIf {player knowsAbout _x == 0} < 0) exitWith { hintSilent "Objective complete. UAV will now land. Disconnected Raven from UAV."; uavDoneT = TRUE; private _theDrone = getConnectedUAVUnit player; _grp = group _theDrone; _posToLand = getMarkerPos "uavLand"; _landPad = createVehicle ["Land_HelipadEmpty_F", _posToLand]; _wp = _grp addWaypoint [_posToLand, 0]; _wp setWaypointType "MOVE"; _wp setWaypointBehaviour "CARELESS"; _wp setWaypointCombatMode "GREEN"; _wp setWaypointStatements ["true","(vehicle this) land 'LAND'"]; player connectTerminalToUAV objNull; }; sleep 2; };]; /* * HERE YOU PUT THE SCRIPT HANDLER INTO * A VARIABLE IN THE MISSION NAMESPACE * FOR LATER USE */ missionNamespace setVariable ["YOU_ScriptHandle", _scriptH, true]; }]; player addEventHandler ["WeaponDisassembled", { /* * HERE YOU CHECK IF THE SCRIPT IS DONE AND IF NOT * YOU TERMINATE IT TO SAVE THE LOOP OVERHEAD SINCE * IT IS NOT NEEDED ANYMORE */ private _scriptH = missionNamespace getVariable ["YOU_ScriptHandle", scriptNull]; // Get the script handle // Check if script is done if (!(scriptDone _scriptH)) { terminate _scriptH; } params ["_unit", "_primaryBag", "_secondaryBag"]; uavPickedUp = TRUE; }]; As always (:|) please note that the code is not tested and should be treated with caution. You have already observed my previous mistakes/errors (which are corrected thanks to Sarogahtyp) so extra caution should be exhibited when trying to use the above code! I understand that this may be overkill for use, since the check you perform doesn't seem to be very heavyweight but I though that it would be nice to present an alternative to lift some of the CPU burden when it is not needed. Feel free to use as seen fit and keep in mind that you don't have to use anything people suggest here. Feel free to use whatever you find useful here as this is the reason people share it here, but please don't feel any pressure to use/try everything just because people suggested it. We all provide as much help as we can because we want to build a nice and strong community that will support everyone in need (regardless of status, seniority and/or knowledge and skills). Having said that, I do hope you'll come back with more questions if you have and with some answers/solutions if you can provide some 🙂.
  11. @sarogahtyp, thanks for the corrections. I did have the typo, thanks for noting out... I'll correct right away. Additionally, you are right, I have incorrectly typed my comment there, which I will correct too. I will also have to change the systemChat command since the number of units is unknown (with findIf). Yet, the use of findIf is as intended and this is why I check for -1 in the condition. Thanks for the corrections and I apologise if I have caused any confusion. I'll try to be less careless in the future.
  12. Not something special to do here. You just replace your code with what I have presented above and in the first if-branch you do what you have to do. In you case you place the uavDoneT = TRUE; code. Generally speaking, it is good practice to avoid writing code that does nothing. This goes specifically to your else branch. Although, technically it does no harm at all (the result is the same since the branch is empty), it can be misleading to people (or yourself) trying to debug and/or maintain your code. With the comments it may be clear that you don't intend to use the else branch but again this may lead someone (or, again, yourself) to think that you may wanted to add some functionality/feature and you either forgot or for some unknown reason (which can cause confusion as to what the "side-effects" the script may have) you didn't manage to implement it. It would be a lot clearer that you don't intend to use the else branch if it was not there at all! It is very good practice to communicate your intend in the code as much as possible. Some "guru" saying go like "code with clear intent is that which does not need comments to be understood" or something like that. Although this may be exaggerated I believe that does communicate the need (?) to make your intentions clear with your code as much as possible. Wherever there is some ambiguity there is room for bugs. Additionally, it is good practice to avoid infinite (or long lasting) loops if you can avoid them. For example, in your problem you could put the if-statement in the condition field of your trigger and avoid the while-loop and the sleep altogether. This is why I suggested the use of the thisList "magic" variable, since this readily available in the scope of the condition field of a trigger. Please let us know if this is not clear and you would require clarifications and/or more help.
  13. You do have a nice answer by NunesSergio but I just wanna add a wee bit of suggestion. According to BIKI, knowsAbout "magic number" is 1.5. This means that when an AI knows about a player or another AI knowsAbout returns a number greater (maybe even equal to but I am not sure about it) to 1.5. You may want to check for that number instead of 0 in the findIf check. So, the check could become _array findIf {player knowsAbout _x < 1.5} I am not sure whether this is "safer" but I believe it is a better approach in the sense that you imitate the engine's behaviour (at least of the AI). Additionally, I believe that you could use the "magic variable" thisList to check for the units in the trigger's area like private _eastUnits = thisList select {(size _x) isEqualTo east}; // East units in trigger area _eastUnits = _eastUnits findIf {(player knowAbout _x) < 1.5}; // Reuse the same variable for to see if there's any AIs not known to the user if (_eastUnits != -1) { systemChat ("There is at least one unit not known to the player"); } else { systemChat "Player knows about all units in the trigger area"; }; where I have split the selection of east units known to the player into two parts to make the code less cluttered. Of course you can one-line it in the if-statement condition check if that suites you best. Please note that these are mere suggestions based on my personal preferences and not some "optimisation" or "best practices" instructions. Furthermore, the above snippets are not tested and should be treated with caution.
  14. Hey, that's a lot of information and I am not sure I completely follow your approach or what exactly you are trying to achieve. I do see some redundancy in the first script you provided in the last answer (for example you have a lot of for-loops that iterate through the same array and you don't really use data from the previous iterations, which means you could possibly fit everything in a single go of the for-loop. Additionally you could use findIf instead of find which is a wee bit faster, especially for large arrays) but I may be mistaken because I don't get exactly what you are trying to achieve. Thanks for sharing though.
  15. In order to get a random number in a specified range you can do // I declare the maximum and minimum values as parameters // You may get them from somewhere else though private _maxNum = 15; // Maximum value private _minNum = 5; // Minimum value // Get a random number between 0 and the value declared in the brackets private _randNum = random [_maxNum - _minNum]; // Get a number between 0 (inclusive) and 15 - 5 = 10 (exclusive) _randNum = _randNum + _minNum; // Add the minimum value (5 in this case) to the random number to move it into the desired range 0 - 10 -> 5 - 15 // _randNum now hold a random (floating point) value between 5 (inclusive) and 15 (exclusive) So, you could just put the random value in a variable and use it in your expression. Alternatively you can call the code 3 times and save the values in three variables if you want to add a different random value to each dimension separately. EDIT: I just realised you have posted the same question in a different thread, so disregard this answer...