Jump to content

vektorboson

Member
  • Content Count

    1009
  • Joined

  • Last visited

  • Medals

Everything posted by vektorboson

  1. For the basics what I will talk about, please take a read at: http://en.wikipedia.org/wiki/Closure_(computer_science) In many functional programming languages closures can be used to fake encapsulation. Thus it is possible to program in a object oriented way with closures. Although I know functional programming (for example Scheme, OCaml) for a long time, I only recently thought about trying to use closures with SQF. The point about closures and functional programming is, that functions are first-class citizens of the programming language; you can pass around functions and manipulate them. The funky thing about SQF is, that you can create functions on the fly (with the compile-command). I took this approach to bind hidden global variables to some 'object methods'. The best way is to just look at the code // File: closure.sqf makePoint2D = { point2DCounter = if(isNil "point2DCounter") then {0} else {point2DCounter+1}; _id = point2DCounter; _this call compile format["point2D%1 = _this;", _id]; point2DDispatch = { _id = _this select 0; _cmd = _this select 1; switch(_cmd) do { case "get-x": {call compile format["point2D%1 select 0", _id]}; case "get-y": {call compile format["point2D%1 select 1", _id]}; case "set-x": {(_this select 2) call compile format["point2D%1 set[0, _this];", _id]}; case "set-y": {(_this select 2) call compile format["point2D%1 set[1, _this];", _id]}; case "hint": { hint str call compile format["point2D%1", _id]; }; }; }; _closure = compile format["([%1] + _this) call point2DDispatch", _id]; _closure }; _pointA = [1, 2] call makePoint2D; assert(["get-x"] call _pointA == 1); assert(["get-y"] call _pointA == 2); ["hint"] call _pointA; ["set-x", 10] call _pointA; ["set-y", 15] call _pointA; assert(["get-x"] call _pointA == 10); assert(["get-y"] call _pointA == 15); _pointB = [3, 4] call makePoint2D; _x = ["get-x"] call _pointB; assert(_x == 3); _y = ["get-y"] call _pointB; assert(_y == 4); // pass reference to _pointA into another script context, modify there x = 20 _pointA execVM "other.sqf"; sleep 0.1; assert(["get-x"] call _pointA == 20); // file: other.sqf ["set-x", 20] call _this; Save those files into a mission, and execVM "closure.sqf". You can also put more ["hint"] call _pointA (or _pointB) into the code, or you change the hint method: case "hint": {player sidechat str call compile format["point2D%1", _id]; }; So instead of a hint, the value is output with sidechat. Short explanation: The global point2DDispatch-function takes an numerical ID as the first argument, the method name as second argument and optional arguments afterwards in the _this variable. We switch over the method name and execute a method specific to the global point2D%1 (replace %1 with the ID). The IDs are tracked through point2DCounter, that is incremented every time a new point2D-object is being created. The whole point is, that we don't want to deal with the global variables at all, thus we create the special function _closure. _closure is a function that binds the ID as the first argument to point2DDispatch, and passes other arguments after the ID. So let's take a look at calling the "set-x" method: ["set-x", 10] call _pointA; _pointA points to the _closure-function that has bound the ID 0 to point2DDispatch, so what is really happening is this: ([0] + ["set-x", 10]) call point2DDispatch; If we instead called _pointB, the same call will be this: ([1] + ["set-x", 10]) call point2DDispatch; When we're passing the _pointA with execVM into another script, we're indeed passing the _closure-function, that has bound the ID. Thus we are accessing the same internal state, but we don't need to explicitly pass around global variable names. Note: Please note that you could already bake the ID into point2DDispatch instead of _closure. I didn't do this, since format has a limit of 2048 characters, thus you can't have bigger objects. Second, the dispatch-function would be duplicated for every object, thus taking a lot of memory, if lots of objects are created.
  2. vektorboson

    Closures in SQF

    Well it is indeed about faking OOP by faking closures, a double-fake so to speak. Nevertheless, I'm pretty interested by the concept of "namespaces" in ArmA II. Actually I'm wondering what it actually will be; since it sounds like they want to cut down usage of global variables, this hopefully means some sort of encapsulation.
  3. vektorboson

    AAN - ArmA Navy

    Nice use of Dangerous Waters screenshots! :D
  4. vektorboson

    Operation Waste Five minutes in Flash

    How about wasting several hours? Fantastic Contraption :icon_mrgreen:
  5. vektorboson

    Closures in SQF

    I don't know about your other code, but the code snippet you posted doesn't show closures. What you are showing is called a 'lambda function' (and dynamic name binding) in many programming languages, which is not necessarily a closure. In your case the lambda function accesses variables that were declared outside the lambda function (through dynamic name binding). In this case you're absolutely right: This is a very old technique, and even I used this technique, for example in my VB_RungeKutta-function at OFPEC (don't know if it is still up there). What I wanted is to simulate closures which can be used in functional languages to do OOP; closures access variables that were defined/declared in the closure's local scope, not outside it. I'm faking this through that global array and returning a 'function' with index into the array hard coded. In case this was already used some time, of course, then it is nothing new. I just have not seen it anywhere, and I didn't see anyone mention it. I looked and searched for something similar but I didn't find it (which of course doesn't mean, it didn't exist before). Of course, if you know about techniques how to do OOP in SQF, than write about it; I'd be glad to know that there is some nice and elegant way how to handle complexity (or what other techniques there are). Â
  6. vektorboson

    ArmA II and 64bit

    Well, making the game world small is another solution. Also by translating [0.0, 0.0] to the center of the map, you'll get twice the range for the same precision (you can use the range [-10.0e5 .. 10.0e5, -10.0e5 .. 10.0e5] without large precision issues). Wonder if this is already implemented...
  7. vektorboson

    ArmA II and 64bit

    That's what I always wanted to ask; do you really use 32bit floating points numbers in ArmA for everything? In OFP you clearly used 32bit, there were clearly floating point precision issues when coordinates were bigger than about 15km. 32bit FP loose precision in the millimeter-range when bigger than approx 10km. One would think that error in the millimeter-range is not a problem, but since those errors sum up, it is definitely a problem. Especially since differences in the centimeter-range may decide about hit or not hit. Since people expect even bigger terrain, and Czernarus looks quite big, how do you solve those precision issues? Do you partition the space, so that you can use locally 32bit FP? Or do you use 64bit FP for positions only, and 32bit FP for the rest?
  8. vektorboson

    Closures in SQF

    I might be wrong, but I thought he wanted to pass the pointer to the array, not a copy? In this specific case, a copy should be made, so that the internal state of the closure can't be changed accidentally through the array that was passed to the constructor. If it wasn't a copy, this would happen! _a = [1, 2]; _point = _a call makePoint2D; _a set [0, 4]; // oops, I changed the internal value of _point!!! Of course the constructor (makePoint2D) may be implemented in another way, for example not taking a parameter at all and returning an object with standard values. As UNN mentioned, very complex systems like CoC CEX can possibly be programmed in a easier way. Also think of such missions like Warfare and other CTIs. As my usage example partially has shown, it's pretty easy to let script threads communicate and share data without explicitly using global variables. I can think of many things that can be implemented in a nice way, like Signals/Slots, delegates or thread synchronization.
  9. vektorboson

    Bye Bye Old BI Forum

    Bye bye from another veteran! Â Last minute SPAM (one banana for every year): Â Â Â Â Â
  10. vektorboson

    Closures in SQF

    Thanks to Spooner here is a much cleaner version: point2D = []; point2DDispatch = { private ["_id", "_cmd", "_point"]; _id = _this select 0; _cmd = _this select 1; _point = point2D select _id; switch(_cmd) do { case "get-x": { _point select 0 }; case "get-y": { _point select 1 }; case "set-x": { _point set [0, _this select 2] }; case "set-y": { _point set [1, _this select 2] }; case "hint": { hint str _point }; }; }; makePoint2D = { private "_id"; _id = count point2D; point2D set [_id, _this + []]; // Store copy, so it can't be changed directly. // Return the closure. compile format["([%1] + _this) call point2DDispatch", _id]; }; _pointA = [1, 2] call makePoint2D; assert(["get-x"] call _pointA == 1); assert(["get-y"] call _pointA == 2); ["hint"] call _pointA; ["set-x", 10] call _pointA; ["set-y", 15] call _pointA; assert(["get-x"] call _pointA == 10); assert(["get-y"] call _pointA == 15); _pointB = [3, 4] call makePoint2D; _x = ["get-x"] call _pointB; assert(_x == 3); _y = ["get-y"] call _pointB; assert(_y == 4); // pass reference to _pointA into another script context, modify there x = 20 _pointA execVM "other.sqf"; sleep 0.1; assert(["get-x"] call _pointA == 20); ["hint"] call _pointA;
  11. vektorboson

    multiple guns error....

    Hi Gnat, it's nothing big, but those brackets around _this are completely unnecessary: Then you can write in your script. Eliminating unnecessary extra variables makes debugging and navigating code easier.
  12. vektorboson

    ArmaLib To .Net - library

    I'm not the original author of ArmAlib, but I can make some educated guesses. Whether this will be available in ArmA 2 depends on: - whether BIS implements some kind of IPC-interface (inter process communication) or even provides a SDK for creating DLLs - time and motivation of Kegetys - what kind of copy-protection and anti-cheat system is built into the game (basically ArmAlib is manipulating ArmA's process space and thus can be considered a 'cheat' or malicious software) Hopefully, there will be something built into the engine.
  13. vektorboson

    ArmAlib v1.0

    I'm trying to take automatic screenshots with the help of ArmAlib. I'm using Qt for grabbing the screen; unluckily it uses BitBlt which seems to be too slow, as it captures the screen while it is drawing into the buffer. Thus I get incompletely drawn maps (my main target is to capture the mapview). Now looking for a solution, it seems that I need to use DirectX to capture the screen, possibly with hooking. Kegetys, in case it isn't too much work for you, could you implement a screenshot command into ArmAlib that returns the path to the saved file? Possibly: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> _path = "screenshot" extCall []; Could you otherwise confirm, that this way would be my best bet? http://www.gamedev.net/community/forums/topic.asp?topic_id=359794 Or possibly injecting a PrintScr-key event into windows and reading from the clipboard?
  14. vektorboson

    CCIP Functions

    Hi, that's not completely correct; I've done some measurements, and I found that there is also lift. Please look at the following graphs. horizontal and vertical speed: horizontal and vertical acceleration: drag/lift coefficient k = 0.5*drag area*drag coeff/mass: As you see in the last graph, the drag coefficient is much higher for the vertical component than for the horizontal. This is because of lift. This also seen in the acceleration graph; you see that there is less vertical deceleration, though gravity is pulling the bomb. Please note, that I have used the GBU AV8B Harrier.
  15. vektorboson

    CCIP Functions

    Well, using the calculation here, I was able to calculate distance without needing to know the actual trajectory or other information. That equation doesn't take into account air drag, so I may be wrong in how well that equation will work. But I presume if we can calculate the percentage of distance lost to air drag from the maximum distance an object would achieve in a vacuum, we'd have our answer. The above formula assumes a completely flat ground; as I said, for a diving attack this may be OK, but in the general case it is not. That formula already knows the height difference between release point and impact point, but even if ignoring drag, you need to simulate the trajectory to find the impact point and travelling distance. Of course you can use above formula to approximate the impact point, check the actual ground height and adjust the height difference till ground height and calculated impact point are near each other. You could also introduce a small correction factor depending on the velocity/range; the longer the projectile flies, the longer it is affected by drag. I think you could find a good factor by simple guessing/testing. I think you're right on here, in that most of the potential problems are likely simple constants. For example, I tried to calculate a free fall object trajectory but it used the exponential function which was very limited in how well it would work. Where do you get an exponential function from?
  16. vektorboson

    CCIP Functions

    The evil thing is, that you indeed need to calculate the "actual" trajectory, since only then you know the impact point, where you can calculate the traveled distance (thus the horizontal distance). Unless I'm misunderstanding you, drag isn't constant, but depends on the square of the velocity and direction. As drag influences velocity, velocity changes; now there's a nice differential equation for the velocity v: dv/dt = gravity accel - 0.5*air density*drag area*drag coefficient*|v|*v/mass I guess we can assume air density to be constant at every height, and I guess that drag area and drag coefficient are merged into ArmA's air friction coefficient. Also I ignored lift force in above equation, as I don't know which ArmA-coefficient is responsible for lift (which is what makes them fly). I also ignored a possible angle of attack (angle between forward vector and velocity vector) which changes the drag area/drag coefficient. Anyway, this equation needs to be integrated twice and the resulting position needs to be checked whether it is near the ground. If it is near or below the ground, you have your impact point, and thus your distance. Otherwise you keep on integrating, or abort after a specific amount of iterations. --- One should make a dive attack when using CCIP, anyway. The reason is quite simple: In a dive the flying direction of the bomb won't change as much, as in a level attack. The trajectory is 'flat' (compared to level attack), thus the computed impact point is more accurate because of less integration/approximation/sensor errors. AFAIR the Falcon 4.0 manual is saying something similar. A similar thing applies to the terrain: You can assume the terrain to be 'flat' in the impact region, thus you need to calculate terrain height only once (or take the average in the impact area).
  17. vektorboson

    Project RACS

    As Wld mentioned that he helped those guys a lot: In case they are using anything from you, be it model parts, textures, scripts, config fragments, you should withdraw permission, too. I hope people understand that this is not about revenge, but about principles. Think about an 'imaginary contract' between yourself and the mod group, which was broken by them; thus they're no longer allowed to use your work. Anyway, hopefully this somehow resolves in a friendly manner.
  18. vektorboson

    MH500

    That's perfectly OK; the RACS style looks cool. Nevertheless I think the RACS (I mean those from BIS) should have used woodland camo from the beginning. Looking at Southern Sahrani in the mission editor with textures on, it looks as if it's more green than sand. If you had the personnel resources, I'd say make them woodland/green, additionally. Perhaps the tan and green (as used on the M113) reversed, so it's more green than tan. Anyway, I'm looking forward to any PRACS-releases in tan.
  19. vektorboson

    flare script adjustments

    Are those missiles using a proximity fuze script? If not, the missiles need to hit the plane/geometry, which is improbable, especially for fast moving aircraft. I tried to condense and simplify your script as much as possible without testing it; you should also post the "flarelaunch.sqs", so we can be sure, you're changing the "flarecount" animation. As I see it, for the first flare the chance to spoof the missile is 20%; for any other flare it's only 10%. <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> ;Missile spoof script by Franze ;Uses elements from BAS's spoof missile script ;and from Moph's range bearing and altitude script _helo = _this select 0 _enemy = _helo select 2 ?(not alive (_helo select 0) ) or (not isengineon (_helo select 0)): exit _weaponname = _helo select 1 ?(_weaponname == "R_M136_AT") or (_weaponname == "R_PG7V_AT") or (_weaponname == "R_PG7VR_AT"): (_helo select 0) vehiclechat "R P G!"; exit ?((_helo select 0) animationphase "flarecount" >= 1): exit _missile = nearestobject [_enemy,_weaponname] _poshelo = getpos (_helo select 0) _posenemy = getpos _missile _x1 = _poshelo select 0 _y1 = _poshelo select 1 _z1 = _poshelo select 2 _x2 = _posenemy select 0 _y2 = _posenemy select 1 _z2 = _posenemy select 2 _x = _x1 - _x2 _y = _y1 - _y2 _range = _missile distance (_helo select 0) ? (_x>=0) and (_y>=0): _theta = atan (abs _x/ abs _y) +180 ? (_x>=0) and (_y<=0): _theta = atan (abs _y/ abs _x) +270 ? (_x<=0) and (_y<=0): _theta = atan (abs _x/ abs _y) ? (_x<=0) and (_y>=0): _theta = atan (abs _y/ abs _x) +90 _dirhelo1 = direction (_helo select 0) _theta = (360 + (_dirhelo1 - _theta))Mod 360 ?(_theta > 15 and _theta <= 45): _oclock = 11 ?(_theta > 45 and _theta <= 75): _oclock = 10 ?(_theta > 75 and _theta <= 105): _oclock = 9 ?(_theta > 105 and _theta <= 135): _oclock = 8 ?(_theta > 135 and _theta <= 165): _oclock = 7 ?(_theta > 165 and _theta <= 195): _oclock = 6 ?(_theta > 195 and _theta <= 225): _oclock = 5 ?(_theta > 225 and _theta <= 255): _oclock = 4 ?(_theta > 255 and _theta <= 285): _oclock = 3 ?(_theta > 285 and _theta <= 315): _oclock = 2 ?(_theta > 315 and _theta <= 345): _oclock = 1 _oclock = 12 _height = "Low" ?_z2 > _z1: _height = "High" (_helo select 0) vehiclechat format ["%1 Missile %2 OClock %3 %4 Meters",_weaponname,_oclock,_height,_range] (_helo select 0) vehicleradio "PRACS_Mirage3_miswarn" _rand = 10 _chance1 = 28 _chance2 = 56 ?(_helo select 0) animationphase "flarecount" <= 0: _rand = 20; _chance1 = 21; _chance2 = 42 _helo exec "\PRACS_Mirage3\scripts\flarelaunch.sqs" ?(random 100 < _rand): exit @ (_missile distance (_helo select 0)) <100 || !alive _missile ?!alive _missile: exit _missile setdir (direction _missile + _chance1 - random _chance2)
  20. vektorboson

    Useful tools

    I don't know if there is already such a thread (probably yes, in that case please direct me to it/merge it into it) In case you have suggestions/tools that fit into this theme, please post your toolset/solution. --- Collaborative text-editor: Gobby I've stumbled unto this seemingly very nice program, which enables collaborative text editing; this can be useful for editing together scripts and configs (and other text-based files). I see a use for editing ad-hoc MP-missions, or helping people with scripts/configs directly instead of having to repost the changes over and over again in new posts. Gobby (collaborative text-editor) --- Version control: Mercurial Some people here are already using version control systems like Subversion (svn); the downside of svn is, that it requires a central repository, so you can only make commits/changes if you're having a connection to it (eg an Internet connection). Mercurial in contrast is a Distributed Version Control System; you can make commits at any time. Every repository is a so-called branch, and sharing your branch is pretty easy: Either you start an ad-hoc server or you simply upload your .hg-directory somewhere on the web. You can use Mercurial to track your changes to an 'official' release of a mission, like your changes to Warfare a.s.o., even there isn't an official repository. There are two variants for Windows-users, the command-line official release, or the GUI-version TortoiseHg: Official mercurial homepage TortoiseHg homepage Hg Book (a manual to Mercurial) --- Text-file merging / "Diff": KDiff3 KDiff3 is a (threeway) text-merging application, especially useful for merging svn- and mercurial-conflicts. This way, whenever your favorite script was changed, you can easily track the differences between the original script version, your edited version and the new 'official' version. KDiff3 homepage --- Text-search/'grep': SourceGlob In case you need to search for some text in many text-files, you can use SourceGlob. This is nice to browse a collection of scripts/configs and to find out how they work together; or you want to find every occurence of a specific class-name. SourceGlob homepage
  21. vektorboson

    flare script adjustments

    It seems that there are many things you can change in that script... First you can leave the lines with "NOID jam...", "NOID icp..." and "NOID dkmm..." out, since I guess that neither JAM, neither ICP RPG-pack and neither the DKMM Mi28 are available for ArmA. (Not so important: What needs a bit of understanding of trigonometrics: All those lines with "atan" could be replace with one line of "atan2") But to come to the main thing: This: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> ?(flarecount <= 0): _rand = 20; _chance1 = 3; _chance2 = 2 Should be replaced with the following: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> ?((_helo select 0) animationPhase "flarecount" <= 0): _rand = 20; _chance1 = 3; _chance2 = 2 Then I'd swap the following lines: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> [(_helo select 0)] exec "\PRACS_Mirage3\scripts\flarelaunch.sqs" ?((_helo select 0) animationphase "flarecount" >= 1): exit Those two lines are responsible for seeing the visual flare-effect, although there aren't any more flares available; I guess that the animation 'flarecount' is changed in the flarelaunch.sqs, right? so you have: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> ?((_helo select 0) animationphase "flarecount" >= 1): exit [(_helo select 0)] exec "\PRACS_Mirage3\scripts\flarelaunch.sqs" Thus, if the flares are expended, the visual effect isn't started anymore. As I see it, there's a 20% chance that the flares spoof the incoming missiles (random 100 < _rand, where _rand is 20); this should be OK, especially if the incoming missiles use a proximity fuze-script. Just to add one thing: I think that the script could be overall shortened to maybe ten lines or less. (sorry for being a smartass, I really should post a refined script, thus really helping you, instead)
  22. vektorboson

    Unfinished stuff

    I don't know about OFPEC, but the dialog- and the drop-tutorial are available on Mapfact: Dialog-tutorial Drop-tutorial I didn't test those, but the English versions should be included. Shame on me, I don't have those tutorials anymore on my HD (neither the released versions, neither the source).
  23. vektorboson

    Unfinished stuff

    Thanks for the mirror  Yep!
  24. vektorboson

    Project RACS

    Go for XEH-compatibility. As I understand this will make your addons work better with ACE (which got me hooked, like many others). As for motivation: I love what you guys are doing; you create a nice and unique mix of vehicles. I'm looking forward to the ground troops, those screens from Lennard are wetting my appetite. You guys make RACS my favorite side to play.
  25. vektorboson

    Operating System,C++,Hardware languages, etc...

    The instruction format (what you call machine code) is a part of the architecture. When you design a CPU, you need to define what instructions your CPU supports, and how those instructions look like. You're worrying too much about that type of performance too early. As you're rather kind of a beginner you're going to encounter other performance bottlenecks. First you should get your algorithms and data structures right. If you're dissatisfied with your game's performance, you run a profiler over a sample session. The profiler tells you which code runs most often and which code takes away most of the time. That's where you should optimize for performance. Premature optimization costs a lot of time an you're never gonna see any results if you worry so much about performance before you've written a single line of code. It never hurts to write platform-independent code; write only platform-dependent code if the profiler says so. I find Linux to be a very nice development platform and a very nice Desktop OS (especially with the KDE 4.x series), so I'm a bit biased when I say go for it. But don't restrict yourself unnecessarily to a single platform. Think of a virtual machine as a program that emulates a CPU: It emulates registers, a stack, memory, a.s.o. The VM takes instructions in a binary format but those aren't executed on the real CPU, but interpreted by a program which manipulates the virtual registers and other pieces of 'virtual hardware'. A VM may emulate a real CPU / real hardware (like ZSNES or those Amiga-Emulators), but it is not necessary. Many scripting languages have a VM that does not resemble any real hardware. Virtual Machines are mostly designed in such a way that it should be possible to build a CPU/hardware that behaves exactly like their software counterpart. In this way you can already program for hardware that does not exist yet. The problem with C++ is that it is a curse because of the complexity of the language (and the pitfalls); otherwise it is a bless because of the huge amount of available, mature libraries. But don't restrict yourself to C++; you should also learn some other languages like for example Python (or Ruby) as those are quite useful utility languages. Learning a functional programming language like Scheme (or LISP) can give you a lot in terms of algorithmic thinking, especially regarding recursion.
×