peachpossum Posted 13 hours ago Posted 13 hours ago 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? option 2.) Use a SWITCHED trigger and list each MAP OBJECT IS DEAD condition for each map_object, separated by an OR condition? 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.
cfrag Posted 7 hours ago Posted 7 hours ago 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.
Mistermann Posted 1 hour ago Posted 1 hour ago 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
peachpossum Posted 1 hour ago Author Posted 1 hour ago 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.
peachpossum Posted 1 hour ago Author Posted 1 hour ago Ah, I found the link to DML; https://www.digitalcombatsimulator.com/en/files/3324851/ 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.
cfrag Posted 1 hour ago Posted 1 hour ago 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: 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
Recommended Posts