Jump to content


  • Content Count

  • Joined

  • Last visited

  • Medals

Community Reputation

9 Neutral

About dwringer

  • Rank
    Staff Sergeant

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. You haven't given us all of your code. If _group represents the group of hvt then the code would function as you desire. Since you are spawning a group and _group refers to that, of course the waypoints are added to _group. What you probably want is to run that script with _group assigned to "group hvt" and it will add the waypoints you want. Sorry I can't be more explicit without seeing exactly the code you are running and exactly how you are calling it.
  2. dwringer

    64-bit Executables Feedback

    An update on the EDEN GUI errors I've been having with the dev branch: With "Small" Interface size and 4k resolution, none of the pull-down menus are functional. They still can have a set value, but the expanding menu never appears so it is impossible to select different options. Pressing alphabet keys will set some of the values inconsistently based on their first letter (?). With the interface set to "Very Small" or "Normal" the pull-down menus function properly with no problems. I have tried this in 32- and 64-bit, with and without mods.
  3. When you have that array of houses, you need to iterate through it to build an average position as a new array. Each position is a 3-element array, so your new array will also be 3-elements: consider each element as its own unique 1-dimensional position (x, y, and z). private ["_meanPosition", "_length", "_component"]; _meanPosition = []; _length = count _findhouses; for "_i" from 0 to 2 do { _component = 0; for "_j" from 0 to (_length - 1) do { _component = _component + (((position (_findhouses select _j)) select _i) / _length); }; _meanPosition pushBack _component; }; This is the same as adding all the x's and dividing by the total, then adding all the y's and dividing by the total, and finally adding all the z's and dividing the total, to yield three position averages (The average 3D position). In this algorithm division is done at each step instead of at the end to avoid accumulating really large sums that could cause problems. Here is a function I have been using, which you can paste in init.sqf or somewhere like that: fnc_vector_mean = { /* Find the mean vector of a list of vectors */ _vectors = _this; private ["_alen", "_component", "_mean"]; _mean = []; _alen = count _vectors; for "_i" from 0 to 2 do { _component = 0; for "_j" from 0 to (_alen - 1) do { _component = _component + (((_vectors select _j) select _i) / _alen); }; _mean pushBack _component; }; _mean }; That is only for 3D vectors, so the name is not very apt, but it would not be complicated to extend it (but you don't need to in this case).
  4. dwringer

    64-bit Executables Feedback

    I haven't done extensive testing because although performance seems better in 64-bit, using the dev branch (32- or 64-bit) caused all pulldown menus in the eden editor to stop functioning. Thus it became impossible to set up trigger activations, etc.
  5. Heh, though I am flattered, that is currently somewhat outside of my intended scope with this project. Since all users of this system have to do is drop the source folders into their mission and add a couple of lines to the init.sqf, it should offer almost as smooth an experience as if it were integrated with an addon. Since much of the system's power derives from creating one's own classes, users are expected to dig into their mission folder somewhat anyway, although typically this need not go much farther than simple drag'n'drop. I've been working with this system for the last several days now and can report there will be at least one significant addition to the next release (it is already available on GitHub from the master branch's root): A version of fnc_tell that uses spawn instead of call to execute methods. This returns a handle to the new execution thread and lets much more complicated methods run asynchronously. The new function is called fnc_tells and otherwise works the same way as fnc_tell. This function was created to aid in a new module with which I've been experimenting as a test of the class system's robustness. That new system, composed primarily of classes, can be found on GitHub in the "opti/" folder and provides a basic framework for running multi-objective optimization algorithms. Don't expect high-performance computation here, as not all the systems are well-optimized (or ever going to be extremely fast, honestly). You can, however, expect usable results. More detailed documentation on this is to come later but it could definitely be worth taking a look at. A quick and dirty example is provided that relies on the mkcivs module (also on GitHub) and optimizes positions around the player's group location for partial LOS and nearby civilians in the global array "civArray". That example is illustrated here: [An example mission and more will be coming soon] EDIT: Ugh... starting to see how ArmA can do "interesting" things with its objects. Fixed the Optimizer example - _this inside the spawn was not behaving the same way as the object it was supposed to represent by the end. Not sure why because it seemed to work for the first loop of calls and then return an old version for the last call. Using the actual object name instead fixed the problem in this case. I regret nothing!
  6. Typically the worst code in the world, called in a spawn context, will not impact your framerate. The best most optimized loop on earth, if "called" directly from a trigger, init.sqf, or initialization, will happily eat all your frames until the game is frozen for 20-30 seconds at a time. Asynchronous contexts are your friend.
  7. That isn't really a complete answer. In general I think you could loop checking nearObjects and applying/removing the disableCollisionWith effect when things came in and out of range, but it might take some fiddling. Saw the above post, I guess that's true, I had assumed the OP misspoke but I think theend3r is right.
  8. Thank you for the advice, and it is an honor to be recognized by such an illustrious forum member. You make the discord sound just so inviting, heh, but I might stick my head in there as I am sure you're right that there is much to gain. I'm not too confident in any of this stuff yet as I'm the only one to my knowledge to be testing it and I never went past trivialities until after I released v1.0 of this class system. I've been trying to break it, though, for the past few days, and surprisingly it has proven robust and a lot faster than I had expected considering the number of function calls going on at times. I share some cynicism about OO too, and there is something to be said for avoiding it, but it is still the right tool for certain jobs and exactly the tool I was wanting in this case. I had checked out a couple of other OO packages in SQF, but didn't see anything as high-level and dynamic (or, some might say, hackish and horrifically unsafe).... This is pretty much an abomination of an homage to Python, mixed with Lisp, slopped together like Christmas dinner leftovers. But as far as I can tell, it works. Thanks again; I still am not committing to anything more than a low profile and a disclaimer that this might not satisfy every use case for now. But, as time permits, I am working on several systems using this class module, and will be sure to post more information as it is available. I also put everything under the MIT license, and it may be painfully obvious that I did not follow the typical community naming convention of prefixing my initials to any function or variable names. That is to emphasize how this is meant to be low-level, experimental, and open to all to make of it what you will. I must leave it at this for now until I get some non-trivial applications going and test things more thoroughly.
  9. A Tutorial Walkthrough - The Marker Class: In order to demonstrate the power of this Class system, and hopefully make it seem more approachable, I will walk through creation of a Marker class that adds the much-desired (by me, at least) functionality to instantiate a marker once and then have unlimited freedom to manipulate it, hide it, or show it again. Without using a Marker class, it takes several calls and the managing of complicated data structures to accomplish what is done here in just a couple of short lines. The Marker class will inherit from the ObjectRoot class (classdef\ObjectRoot.hpp) that is provided with the class system files. ObjectRoot gives us the ability to send the messages "_getf" <value> and "_setf" <key> <value> [sent with the fnc_tell function] for conveniently managing local instance variables. This walkthrough guides us through the creation of classdef\Marker.hpp, which can be located at https://github.com/dwringer/a3system/blob/master/classdef/Marker.hpp Initialization: Following the BIS Community Wiki documentation for createMarker, we find that the following minimum information is required to make a new marker: name position shape type (if ICON) size (if RECTANGLE, ELLIPSE) We wish to simplify marker creation as much as possible, so here we will no longer take "marker name" from the user as a creation parameter. Instead, we will keep a global variable called MarkerIndex and increment it for a unique value we can append to the name of each new marker. MarkerIndex = 0; Our initialization method for the new Marker class will take the remaining necessary parameters, and we will allow nil to be used in place of "type" or "size" depending on which kind of marker is being made (area or icon). With this, we can create new Marker instances at will with a call like: //mkr = ["Marker", <position>, <shape>, <type>, <size>] call fnc_new; mkr = ["Marker", position player, "ELLIPSE", nil, [10, 10]] call fnc_new; Methods: This marker will still not be visible - all we have done is configure the new instance. We still need a "show" method to reveal the marker on the map. This could be tacked onto the end of our initializer as well, but it needs to exist as a separate method. You can see our show method reads a lot more variables than what we configured in the initializer. This lets us set more than the minimum required for a marker by setting the appropriate instance variables (with "_setf" calls). More on that in a moment. A call to [mkr, "show"] call fnc_tell; will now reveal the marker instance on the map. In order to hide the marker again, we will use another method: "hide". You may note that reconfiguring the marker instance variables using "_setf" will not have any effect on the existing marker on the map. For that reason, we simply create a "redraw" method to call "hide" and "show" in succession whenever the marker is already visible. Finally, we implement trivial methods to set each configuration variable and then call redraw. Using: Combining all of the above together into classdef\Marker.hpp and adding the line #include <classdef\Marker.hpp> to our init.sqf (after including include\classes.hpp) gives us access to the new object interface, and we can use it as one might expect: // Create and show a new marker: mkr = ["Marker", position player, "RECTANGLE", nil, [5, 5]] call fnc_new; [mkr, "show"] call fnc_tell; // Reorient the marker: [mkr, "set_direction", 45] call fnc_tell; // Change marker color: [mkr, "set_color", "ColorGreen"] call fnc_tell; // Change marker size: [mkr, "set_size", [10, 10]] call fnc_tell; // Hide marker again: [mkr, "hide"] call fnc_tell; This is just one simple example of how to use object orientation with the SQF Classes module to facilitate simpler, more powerful options in the editor and during scenario design. Markers were a prime candidate for this technique because of the overhead involved every time a marker is to be created, altered, or destroyed. That overhead can be wrapped up into the class and its methods, and then ignored even as the class can be reused in different projects or even extended via inheritance and subclassing. I hope this may interest you in trying to create your own classes and sharing them with the community, or at least implementing them in your own scenarios to make things easier on yourself! Edited to fix a bug that shows up in certain cases when using nil as a parameter.
  10. In that case they will engage, but continue making their way along the waypoints. You would need to explicitly give them a seek and destroy waypoint to activate when they detected enemies, and then switch them back to their normal waypoints once the enemies are gone. There are a number of ways to do this, but none are that simple. I would say a solution using "Skip Waypoint" triggers (I think that's what they're called... used to be "SWITCH") is probably the simplest. You may have some luck also if you set them to "Open Fire" instead of the default "Open Fire, Keep Formation" (these used to be called "Open Fire, Engage at Will", and "Open Fire", [reversed] which makes things confusing to say the least). You may need to do some testing to determine under what circumstances the units will abandon waypoints to go after enemies. That may suffice instead of using any seek-and-destroy waypoint switching.
  11. dwringer

    setUnitPos not working ?

    I'm not sure, but I tried using it the other day in response to a question I saw on another forum and found it not to work, also. It seemed like it might have possibly done something, but as soon as the units detected enemies they ignored it. Might have been a coincidence, and it never worked at all, but I did not investigate further.
  12. dwringer

    Executing script

    What? The editor won't even allow you to write "this spawn {}" in a trigger activation or init field. You HAVE to assign it to something, '_nil' is a convention because the results are not used in this case. _nil = this spawn {}; is fine, but this spawn {}; won't even let you close the dialog window. EDIT: specifically, the error message is: What I meant was, the game will not allow you to return a variable from whatever you insert into Init. It expects "Nothing" [which is precisely what an assignment (to _nil or anything else) returns] EDIT 2: I can see how in some contexts it may be desirable to wait for the script to finish (or check its value) during init. In that case, you're right, assignment to _nil is the wrong pattern. It is perfectly fine in most cases, though, and certainly better than "nil =" or "0 =" which are plainly invalid. EDIT 3: Perhaps what we should start doing is "_dontCare =" or "_handle ="... I did that for a while, but honestly, "_nil =" is just a lot shorter, clearer than "_dc =", and works just as well for something that's never going to be seen again.
  13. dwringer

    Executing script

    In that case you can just try: _nil = [ [GKB_aa1, GKB_aa2, GKB_aa3], [[0, 4500], [7000, 8000], [1000, 500]], 20 + random 100, 0.1, {alive GKB_radar}] spawn GKB_fnc_randomAAFire; If you add "_nil =" at the beginning it won't be trying to return anything to the game where it isn't supposed to. (of course, you will need to replace the parameters with things that make sense in your case... I presume you don't have any of the units GKB_aa1.. or GKB_radar unless you named them that to work with this specifically)
  14. dwringer

    Executing script

    You may be right... since this is a function it must be compiled before you can say "spawn GKB_fnc_randomAAFire" as in the example. <EDIT: try it with no ".sqf" here> Assuming that example syntax is correct, try adding this to the file "init.sqf" in your mission directory: GKB_fnc_randomAAFire = compile preprocessfile "path\to\the\script.sqf"; Where, of course, you insert the actual relative path from your mission directory. I.e if it isn't in a subfolder, just write "scriptname.sqf" (whatever the filename is). EDIT: I'm not sure that example syntax IS correct; try dropping the ".sqf" when you actually spawn it. EDIT 2: backslashes
  15. SQF Classes for ArmA 3 Edited - release updated with a couple of bugfixes - if you downloaded prior to 6pm GMT on 29 October then please re-download to get the corrected files. "If . . . [the] fact [that brutes abstract not] be made the distinguishing property of that sort of animal, I fear a great many of those that pass for men must be reckoned into their number." -- George Berkeley Many times when scripting in SQF it may occur that implementing object-oriented techniques can simplify or enhance certain abstractions. The technique of using getVariable/setVariable on a unit or gamelogic to store function code or references specific to that unit's situation is a common pattern found in many missions and modules. Here, that idea is taken one step farther: instead of storing functions on game objects, we store an array of class names (representing a chain of inheritance or a mixture of interfaces). Meanwhile, a master Classes array holds a subarray for each defined class, containing a function definition for each class method. With this arrangement and just a handful of primitive functions, an unlimited variety of classes and methods can be declared on-the-fly while a mission is running. Release (.zip): https://github.com/dwringer/a3system/releases/tag/v1.0 Code: http://github.com/dwringer/a3system/tree/master/ClassDemo.Tanoa This is a selection of modules drawn from a larger repository I keep at http://www.github.com/dwringer/a3system/. There, more recent versions of these modules can often be found. I also placed other modules I created over the years, which are of variable quality and may or may not be worth a look. Class layout Lambda Macros Example overview This will demonstrate how to create abstract instances and send messages (method calls) to them. The included example is a mission with four men (crew_1..crew_4) and two vehicles (car_1, car_2). You may easily duplicate it in a different map if you don't have Tanoa available. There is a single Radio Alpha trigger, upon whose activation the following scripts are executed: CG = ["CrewUnitGroup"] call fnc_new; [CG, "assign", crew_1, "driver"] call fnc_tell; [CG, "assign", crew_2, "gunner"] call fnc_tell; [CG, "assign", crew_3, "driver"] call fnc_tell; [CG, "assign", crew_4, "gunner"] call fnc_tell; [CG, "assign", car_1, "vehicle"] call fnc_tell; [CG, "assign", car_2, "vehicle"] call fnc_tell; [CG, "board_instant"] call fnc_tell; Here, fnc_new is how we create a new instance. It accepts the class name and any init parameters appended to it (here there are none). We could also put a Game Logic in the editor instead of using fnc_new, and in its init use the following: _nil = this spawn { waitUntil {not isNil "ClassesInitialized"}; [_this, "CrewUnitGroup"] call fnc_instance; .. rest of code .. }; The method calls are actually made with fnc_tell, which takes as parameters the class instance, method name, and subsequently each method parameter. Thus, all methods to all classes are defined and called using a standardized syntax and set of functions which have been precompiled. Since fnc_instance makes an instance out of an existing object, we can also use it for creating class inheritance. Consider the following: DEFCLASS("MySubClass") ["_self"] DO { [_self, "SuperClass"] call fnc_instance; .. rest of code .. _self } ENDCLASS; Now, MySubClass inherits all the methods from SuperClass. Each game object keeps an ordered list of its class assignments, so if a method is not found on MySubClass it will be looked up on SuperClass. I have provided the macros SUPER and SUPER_ARGS in include\classes.hpp to facilitate subclassing from within classdef header files. If you want to create a subclass method that implements a superclass method under a different name, that can be done by looking up the class alist in the Classes global alist and using the function contained there as a new method. In classdef files, this has a macro called ALIAS(subclass, subclass_method, superclass, superclass_method). Another example Without further ado, the link to the repository containing the above example mission folder and all required modules is: Release (.zip): https://github.com/dwringer/a3system/releases/tag/v1.0 Code: http://github.com/dwringer/a3system/tree/master/ClassDemo.Tanoa Good luck, and if anyone creates some useful classes or a cool class tree, I'd love to hear about it. Even if this just serves as an example of what can be done to (ab)use SQF, I am satisfied. "No point in mentioning these bats, I thought. Poor bastard will see them soon enough." -- Raoul Duke Edited - release updated with a couple of bugfixes - if you downloaded prior to 6pm GMT on 29 October then please redownload to get the corrected files. There were changes made to fnc_tell and fnc_filter related to nil values being passed as parameters. Edited - added another example section