Jump to content

[SOLVED] More scripting help - Create a randomly dispersed & timed array of flak explosions


Recommended Posts

Posted (edited)

Greetings!

What I'm trying to achieve:
----------------------------

To create a volume of airburst explosions, to simulate flak dispersed horizontally and vertically around a point, with random (short) delays between explosions.

What I did using standard triggers:
------------------------------------

1. As a test, I spread nine small trigger zones around an airfield, named Explosion-1, -2 etc.
2. In ME, I made an action to spit out random values for FLAG 2 between 2-9.
3. Then I made a SWITCHED CONDITION for each of the random values. Each line checks the value of FLAG 2, fires the explosion, then re-sets the flag to value 1 to continue the loop.
4. In the ACTIONS panel, I changed the altitude of the explosion in each line, so that the flak bursts are spread vertically and well as horizontally.
5. I kept the altitude low (<200) so I could observe it more easily from a parked plane.
6. I kept the volume (power) of the explosions low (100) in my test but this could be set to 1 if the effect desired was visual rather than destructive.
7. Here are some screenshots of the map and triggers panel, if that's helpful:

Spoiler

JC-flak-1.jpg

JC-flak-2.jpg

JC-flak-3.jpg

JC-flak-4.jpg

JC-flak-5.jpg

The above set-up works well. However, I'd love to be able to do all triggering processes in a script.

It seems to me (still learning lua) that the script might do the following things:
----------------------------------------------------------------------------------

1. Get the vec3 coordinates for Point X in the middle of the area (perhaps the coordinates of a suitably placed vehicle) using a .getPoint thingie.
2. Create a number of new points (say, Points A-J for a ten-point field) scattered randomly (horizontally and vertically) around Point X, by making ten new x,y and z vec3 coordinates for each Point A-J. I think this could be done using a math.random thingie for x,y,z values? Perhaps then all the new coordinates could be stored in a table using a local BurstPoints_Table thingie?
3. Then create some code to detonate an EXPLOSION event at each of the randomly generated Points A-J at random (short, say 1-3 seconds) time intervals. For more timing randomness, perhaps one explosive array could be superimposed on top of another, running from a different mission time start point?
4. Continue this process until another trigger stops the loop, such as after a defined time or when a unit leaves the area. I have no idea how that could be done!

In summary, the script would:
-------------------------------
1. Get a starting point.
2. Create randomly scattered points around it.
3. When triggered, randomly detonate explosions at those points.
4. Stop when required.

Taking it to the next level:
---------------------------

A next-level version of such a script might take the coordinates of a moving aircraft every few seconds and create the array of explosions in a pattern ahead and to the sides of the aircraft. Kind of a moving flak field, as though the AA gunners were tracking the aircraft/group. That might be difficult to script?

My request:
------------

I'd be *super-grateful* if one of the community scripting wizards could give the main concept some thought (the next-level stuff can wait maybe). I am still on the lua learning pathway so I am yet to make the jump from know roughly what the script needs to do, to actually writing the code. My attempts so far produced errors or nothing. Previously cfrag and veteran66 helped me with some scripting, so I'm hoping they or others might be willing to continue to teach this stuff. Thanks and best wishes from Australia, John

Edited by johnboy

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

Posted

Perhaps my post was in the tldr category? 😉
Here's what I have been able to come up with so far, with help from a scripting video by Ditch3r (highly recommended). This creates a single airburst explosion, offset from a unit on the x, y, and z axes. What I need to do next is find a way to produce a bunch of similar offsets, then detonate an explosion in each point, at a random time interval, for a period of time (say, 60 seconds). Can anyone help? John 

--Create an explosion offset in x,y and z space from a unit

function ExplodeNearUnit(GroupName)
ExplodeNearUnit = Group.getByName( GroupName ):getUnits()
ExplodeVec3 = ExplodeNearUnit[1]:getPoint()
ExplodeVec3.x = ExplodeVec3.x + math.random(-100,100)
ExplodeVec3.z = ExplodeVec3.z + math.random(-100,100)
ExplodeVec3.y = ExplodeVec3.y + math.random(0,200)
trigger.action.explosion(ExplodeVec3, 100)     -- Vec3 position, power
end
ExplodeNearUnit("Unit1")

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

Posted
2 hours ago, johnboy said:

What I need to do next is find a way to produce a bunch of similar offsets, then detonate an explosion in each point, at a random time interval, for a period of time (say, 60 seconds). Can anyone help? John 

What you want to do is to invoke ExplodeNearUnit() for a number of time (say 45) staggered over the next 60 seconds. Thankfully that's easily done with timer.scheduleFunction() (you'll need a slight adaptation method for ExplodeNearUnit, see below). Randomize the time that the explosion happens, and you should be done. In all, only a few more lines


function ExplodeNearUnit(GroupName)
	ExplodeNearUnit = Group.getByName( GroupName ):getUnits()
	ExplodeVec3 = ExplodeNearUnit[1]:getPoint()
	ExplodeVec3.x = ExplodeVec3.x + math.random(-100,100)
	ExplodeVec3.z = ExplodeVec3.z + math.random(-100,100)
	ExplodeVec3.y = ExplodeVec3.y + math.random(0,200)
	trigger.action.explosion(ExplodeVec3, 100)     -- Vec3 position, power
end

-- make ExplodeNearUnit callable from scheduleFunction
function timedExplosionNear(args)
	ExplodeNearUnit(args[1])
end

-- create 45 explosions in the next randomly picked 60 seconds
for i=1, 45 do 
	timer.scheduleFunction(timedExplosionNear, {"Unit1"}, timer.getTime() + math.random(60))
end

 

Posted (edited)
15 hours ago, cfrag said:

What you want to do is to invoke ExplodeNearUnit() for a number of time (say 45) staggered over the next 60 seconds. Thankfully that's easily done with timer.scheduleFunction() (you'll need a slight adaptation method for ExplodeNearUnit, see below). Randomize the time that the explosion happens, and you should be done. In all, only a few more lines

Hi Chris, thanks very much for taking a look at this for me. I'm afraid I'm getting errors when I run the script in DCS (see below). I've double-checked spelling etc but I don't really know enough to troubleshoot the problem. Is there something I'm supposed to add to the script, perhaps? Sorry to bother you with this. John

Spoiler

Error-pic-gigapixel.jpg

 

Edited by johnboy

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

Posted (edited)
22 hours ago, johnboy said:

ExplodeNearUnit("Unit1")

A fast answer:

Is this a UNIT's or a GROUP's name ? Does exist in the mission ?

Edited by ADHS

Democracy was already invented, while Scrat was eating oak fruits.

Posted
9 minutes ago, ADHS said:

Is the a UNIT or a GROUP name ?

Hey mate, it's both; the Group is Unit1 and so is the unit. Is that a problem? John

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

Posted

 

19 minutes ago, ADHS said:

No problem from the time that do exists in the mission.

Still puzzled. In case the naming convention was the problem, I tried changing the name of the Group and Unit so that the Group was "Convoy1" and the unit was "Unit1", and also tried the Group name as "Unit1" and the unit as "Unit1-1". Both arrangements crashed to errors. I also made sure the script was being freshly injected into the mission file, in case there was an older script still embedded. No joy. When I run the mission with only the short script I posted above originally, the script works fine and I get one explosion in a random location, as expected. If it's any help, I've attached the mission file (that works) with just my simple first version embedded. Once again, I really appreciate any help that's offered! John

FlakTesting-1.miz

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

Posted

Sorry mate but i am out of time here and have to go.
Try Unit.getByName(GROUP[i]) as you are based on unit.
And for multiple explossions use a random for to loop.

  • Like 1

Democracy was already invented, while Scrat was eating oak fruits.

Posted (edited)

Okay, we have a solution. By removing the function:

function timedExplosionNear(args)
	ExplodeNearUnit(args[1])
end

 ...the script ran perfectly, producing a nice volume of random bursts around and above the unit. See pic below. Because I'm a mere lua apprentice, I don't fully understand why the 'args' function was a problem. But, it works. The Group name is Unit1 and the unit name is Unit1-1, but the unit name doesn't matter it seems. The modified/working script is also below. Thanks all for your interest and assistance! John

Spoiler

Flak-test.jpg

Spoiler

-- Create airburst explosions in a volume around and above a unit, to simulate flak.

function ExplodeNearUnit(GroupName)
    ExplodeNearUnit = Group.getByName( GroupName ):getUnits()
    ExplodeVec3 = ExplodeNearUnit[1]:getPoint()
    ExplodeVec3.x = ExplodeVec3.x + math.random(-200,200)
    ExplodeVec3.z = ExplodeVec3.z + math.random(-200,200)
    ExplodeVec3.y = ExplodeVec3.y + math.random(50,200) -- the previous setting of the lower y-axis value to zero produced occasional ground bursts
    trigger.action.explosion(ExplodeVec3, 100)     -- Vec3 position, power
end

-- Create 45 explosions in the next randomly picked 60 seconds - this part added by cfrag. Thank you!
for i=1, 45 do 
    timer.scheduleFunction(ExplodeNearUnit, "Unit1", timer.getTime() + math.random(60))
end

 

Edited by johnboy
  • Like 1

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

  • johnboy changed the title to [SOLVED] More scripting help - Create a randomly dispersed & timed array of flak explosions
Posted (edited)
9 hours ago, johnboy said:

the script ran perfectly,

That threw me until I messed around with it myself. And I'm amazed: you actually managed to pull off a fully-blown Jedi code-trick😎

Let me explain: While reporting on the error that you received, you probably did not realize a small strange detail and therefore didn't mention it happening: the script works once (you hear one (1) BOOM!), and then suddenly it starts failing by throwing the error on all subsequent invocations. And then you managed to get the script to run although it really should not. Absolutely fantastic. 

This is because in the original script you (probably erroneously) redefine the method ExplodeNearUnit by assigning it the result of Group.getByName():getUnits()

function ExplodeNearUnit(GroupName)
    ExplodeNearUnit = Group.getByName( GroupName ):getUnits() -- this redefines the method!!!
    ExplodeVec3 = ExplodeNearUnit[1]:getPoint()
    ExplodeVec3.x = ExplodeVec3.x + math.random(-100,100)
    ExplodeVec3.z = ExplodeVec3.z + math.random(-100,100)
    ExplodeVec3.y = ExplodeVec3.y + math.random(0,200)
    trigger.action.explosion(ExplodeVec3, 100)     -- Vec3 position, power
end

As it happens in scripting so often, the ONLY condition where this isn't immediately obvious and will work without an error is when you schedule ExplodeNearUnit() directly for invocation like timer.scheduleFunction() and before it has been invoked even once. This unlikely combination of things is exactly what you did, Master Jedi 🙂! [nod of respect]

And of course, this then masks the erroneous redefinition of ExplodeNearUnit (because at the time the call is scheduled it hasn't been redefined and the scheduling process assigns the correct method location). That is the reason why it works even though it should (and will) not under any other circumstances (simply invoke ExplodeNearUnit directly from the loop to see it fail on the second and all other invocation).

The workaround is easy: either rename the variable that you assign the result of Group.getByName():getUnits() or add a 'local' tag that prevents the global function being overwritten by the result:

local ExplodeNearUnit = Group.getByName( GroupName ):getUnits()

The corrected and fully timer-compatible script that will also work with non-timed invocations:

function ExplodeNearUnit(GroupName)
	local ExplodeNearUnit = Group.getByName( GroupName ):getUnits() -- local!!!
	ExplodeVec3 = ExplodeNearUnit[1]:getPoint()
	ExplodeVec3.x = ExplodeVec3.x + math.random(-100,100)
	ExplodeVec3.z = ExplodeVec3.z + math.random(-100,100)
	ExplodeVec3.y = ExplodeVec3.y + math.random(50,200)
	trigger.action.explosion(ExplodeVec3, 100)     -- Vec3 position, power
end

-- make ExplodeNearUnit callable from scheduleFunction
function timedExplosionNear(args)
	ExplodeNearUnit(args[1])
end

-- create 45 explosions in the next randomly picked 60 seconds
for i=1, 45 do 
	timer.scheduleFunction(timedExplosionNear, {"Unit1"}, timer.getTime() + math.random(60))
end

Cheers, and thank you for a great sunday-morning mystery 🙂 

-ch

Edited by cfrag
  • Like 1
Posted

Wow! From coding noob to Jedi in one day! I've re-read your explanation half a dozen times to make sure I understand it. I'm convinced that lua coding is really black magic in disguise! Thank you for finding and fixing the gremlin! *thumbsup*

Cheers, John

 

  • Like 1

Intel i7-2600K 3.4Ghz

ASUS P8P67 EVO Motherboard B3

Kingston HyperX KHX1600C9D3K2/8GX (2x4GB) DDR3

OCZ RevoDrive PCI-Express SSD 120GB

Corsair Hydro Series H70 CPU Cooler

2 xWestern Digital Caviar Black 1TB WD1002FAEX

TM Warthog Hotas

TrackIR 5 Pro

 

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...