Jump to content

Recommended Posts

Posted

Hi All. 

I am curious about a couple of mission design approaches that may help improve performance

Say I have a bunch of map_objects defined at a factory somewhere, and there are many of them.
If I wanted to detect when each map_object was destroyed, I could use the trigger condition MAP OBJECT IS DEAD for each map_object, and have a trigger action play a short sound and display a message.

If I have a lot of map_objects defined in the mission, which approach would be better for increasing game performance?

option 1.) Use a ONCE trigger for each MAP OBJECT IS DEAD condition?

map_obj_detect_opt1.jpg

option 2.) Use a SWITCHED trigger and list each MAP OBJECT IS DEAD condition for each map_object, separated by an OR condition?

map_obj_detect_opt2.jpg

I've attached missions with each example. I realize the example missions may be too small to see any difference in performance between these options, but if I scaled up the objects by an order of magnitude would it matter then?

A few other questions;

- Would the better approach for detecting the death of map_objects also be better for static and/or ground units?

- Is there a way to list all the flags defined in a mission?

- When detecting the death of a static, is it better to use the condition:GROUP IS DEAD or the condition:UNIT IS DEAD?

Thanks for your feedback.

peachpossum

 

cw_germany_map_obs_detect_option1.miz cw_germany_map_obs_detect_option2.miz

Windows 11 Pro 64-bit
i7-14700k 3.4 GHz, 64 GB DDR5-6000 MHz,
Samsung 980 pro NVMe for DCS drive.
ASUS 790-F ROG Strix Gaming Wifi LGA 1700,
nVidia RTX 4090, Dell Ultrasharp U3818DW 3840x1600 60Hz.

Posted

Please be advised that what I say below is merely based on my experience, not a deeper knowledge of MSE's implementation

5 hours ago, peachpossum said:

which approach would be better for increasing game performance?

They are nearly identical, with the second approach having a minuscule advantage since it requires fewer main loop cycles, but it really comes down to how triggers evaluate the OR clause. I do not think that either will have a noticeable advantage over the other. 

If you know how to do that, you would be better served with a script that does these checks. Since they are map objects, you can then change the periodicity of checks from once per second (as is done for triggers) to once every ten seconds (or longer), shoring up performance cycles. Checking if map objects are destroyed usually isn't a time critical task.

5 hours ago, peachpossum said:

- Would the better approach for detecting the death of map_objects also be better for static and/or ground units?

I believe similar points apply to this. I strongly recommend that you define what you are trying to achieve with this before settling on the method of how to achieve that, lest you fall into the trap of premature optimization. Also, you may want to take into account serviceability: what is easier for you to maintain: 10 rules of one each, or one rule of 10 conditions? Neither is easy nor user-friendly, so your choices are always going to be bad.

5 hours ago, peachpossum said:

- Is there a way to list all the flags defined in a mission?

Not in ME. You could write a script that parses/analyses a miz file and then dumps all the flags that are referenced in the mission's trigger rules. You'd then also want to add a step to see which flags are only referenced once or one way (a good sign that a flag is used wrong is when a flag is only written to or read from). DML's debugger does this, but only for flags that are used/defined in DML's context, but not for flags that are read from or written to with trigger rules nor scripts.

5 hours ago, peachpossum said:

- When detecting the death of a static, is it better to use the condition:GROUP IS DEAD or the condition:UNIT IS DEAD?

That would rather depend on how you placed the static. Using ME, statics are one-unit groups. Using scripts, you can place multi-objects statics. From a logic perspective, it's cleaner to go with UNIT, as it isn't guaranteed that ED will keep that single-unit group for statics, and you are relying on an implicit assumption that the static is in a single-unit group. Use UNIT to ensure that your mission is future-proof.

 

 

Posted

Regarding sounds.   If multiple objects are destroyed together DCS will not optimize the sound playback so they are all heard.

Sounds will step on one another and depending on timing won't achieve what you're looking for. 

Text to screen will work as expected however.

System Specs:

Spoiler

📻Callsign:Kandy  💻Processor:13th Gen Intel(R) Core(TM) i9-13900K - 🧠RAM: 64GB - 🎥Video Card: NVIDIA RTX 4090 - 🥽 Display: Pimax 8kx VR Headset - 🕹️Accessories:  VKB Gunfighter III MCG Ultimate, VKB STECS Standard, Thrustmaster TPR Pedals, Simshaker JetPad, Predator HOTAS Mounts, 3D Printed Flight Button Box 

📹 Video Capture Software:  Open Broadcaster Software (OBS), 🎞️ Video Editing Software:  PowerDirector 365

Into The Jungle Apache Campaign - Griffins  Kiowa Campaign - Assassins  Thrustmaster TWCS Mod

 

Posted

Hey cfrag,

 

Thank you for the thoughtful response. I hadn't considered using scripting to check for map_object deaths. The ability to increase the 1 second periodicity of checking for map_object deaths is really interesting and worth learning more about how to script this. 

My scripting knowledge is very limited to using simple MIST or MOOSE scripts, the latter of which I really struggle to understand when I drill down into the specific AI or core functions.

Would detecting the deaths of map_objects (or statics or ground vehicles, etc.) require using the aforementioned scripting tools, or would the Simulator Scripting Engine tools be the right place to start learning how to do this with scripting?  

I'm not familiar with DML's debugger, but I see you've posted a tool based on DML on ED's Users files site.

peachpossum

Hi Mistermann,

 

Thank you for the reply regarding sounds. I usually use very short duration sounds for such events as the death of an object, mostly to draw the attention of the user to the text message that I program to appear. If I need a sound of with a sufficient duration such as announcing a new objective or such, I will often delay it to play after the duration of the previous text message, which is usually 25 seconds or longer.

peachpossum

Windows 11 Pro 64-bit
i7-14700k 3.4 GHz, 64 GB DDR5-6000 MHz,
Samsung 980 pro NVMe for DCS drive.
ASUS 790-F ROG Strix Gaming Wifi LGA 1700,
nVidia RTX 4090, Dell Ultrasharp U3818DW 3840x1600 60Hz.

Posted
11 hours ago, peachpossum said:

Is there a way to list all the flags defined in a mission?

It irked me to not be able to provide a better solution. Here it is: as small script to cross-reference all flags that you are referencing in trigger rules (NOT in scripts!), and it will also tell you if a flag is used in a suspicious way (i. e. it is only read or written to, usually the result of a misspelled flag name).

Run the script AT START, and you will see something like this:

image.png

In that miz (see attached), the flags "1", "all is lost", "ghi", "abc", "def" and "jkl" are all only either read or written to (in the rules that are in square brackets"[","]"), while the flag named "123456" is both written and read, and is probably used correctly in that miz.

There are a total of 7 flags used in the miz by the trigger rules (again, not inside scripts).

Here's the script itself, run at start

Spoiler

fxref = {}
fxref.readFlags = {}
fxref.writeFlags = {}
fxref.verbose = false
function fxref.updateFlag(theDict, flagname, who)
    local theFlag = theDict[flagname]
    if not theFlag then 
        theFlag = {}
    end
    if not theFlag[who] then 
        theFlag[who] = 1
    else 
        theFlag[who] = theFlag[who] + 1
    end
    theDict[flagname] = theFlag
    return theFlag -- not really needed
end

function fxref.readFlagNamed(flagname, who)
    fxref.updateFlag(fxref.readFlags, flagname, who)
    if fxref.verbose then 
        trigger.action.outText("Flag <" .. flagname .. "> read by rule <" .. who .. ">", 30)
    end
end

function fxref.writeFlagNamed(flagname, who)
    fxref.updateFlag(fxref.writeFlags, flagname, who)
    if fxref.verbose then 
        trigger.action.outText("Flag <" .. flagname .. "> changed by rule <" .. who .. ">", 30)
    end
end


function fxref.collectReadWrite()
    -- collect all flags that read by a trigger rule 
    local Trules = env.mission.trigrules -- an array 
    if not Trules then return nil end 
    for idx, aRule in pairs(Trules) do 
        -- flags are written actions 
        local actions = aRule.actions 
        if actions then 
            for idy, anAction in pairs(actions) do 
                if anAction.flag then 
                    -- actions SET actions 
                    fxref.readFlagNamed(anAction.flag, aRule.comment)
                end 
            end
        else 
            trigger.action.outText("trigger rule <" .. aRule.comment .. "> has no actions", 30)
        end 
        -- flags are read in conditions 
        local conditions = aRule.rules 
        if conditions then 
            for idy, aCondition in pairs(conditions) do 
                if aCondition.flag then 
                    -- actions SET actions 
                    fxref.writeFlagNamed(aCondition.flag, aRule.comment)
                end 
            end
        else 
            trigger.action.outText("trigger rule <" .. aRule.comment .. "> has no conditions", 30)        
        end
    end
end

function fxref.xref()
    -- find all flags that are read only or write only, i.e. used wrong 
    local hasref = {}
    local badref = {}
    local allref = {}
    local count = 0 
    for name, aFlag in pairs(fxref.readFlags) do 
        -- see if it also has a corresponding mention in readFlag 
        if fxref.writeFlags[name] then 
            -- well behaved
            hasref[name] = aFlag 
        else 
            -- is only read 
            badref[name] = aFlag
        end
        allref[name] = aFlag
        count = count + 1
    end

    for name, aFlag in pairs(fxref.writeFlags) do 
        -- see if it also has a corresponding mention in writeFlag 
        if fxref.readFlags[name] then 
            -- well behaved, we already procced this
        else 
            -- is only read 
            badref[name] = aFlag
            allref[name] = aFlag
            count = count + 1
        end
    end
    
    local rep = "Flag xref running:"
    rep = rep .. "\n** ONE-SIDED flags (erroneous/bad use):"
    for name, aFlag in pairs(badref) do 
        rep = rep .. "\n    * <" .. name .. ">: "
        local conj = "["
        for who, cnt in pairs(aFlag) do 
            rep = rep .. conj .. who
            conj = ", "
        end 
        rep = rep .. "]"
    end 
    rep = rep .. ("\n\n++  All other flags used (good, matched pair use or better):")
    for name, aFlag in pairs(hasref) do 
        rep = rep .. "\n    : <" .. name .. ">"
    end 
    rep = rep .. "\nFlag xref complete, <" .. count .. "> flags processed\n"

    trigger.action.outText(rep, 30)
end 

-- run the ref 
fxref.collectReadWrite() -- collect flags use
fxref.xref() -- run xref and report 
 

Demo miz below.

Hope this helps. Enjoy,

-ch

flags in the log ruler.miz

  • Recently Browsing   0 members

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