DonCalzone Posted July 16, 2020 Posted July 16, 2020 Hey, I'm trying to use the Unit.getAmmo() function to check how many rounds a certain unit has fired. I was able to return the ammo count but it's two values for every gun seperately (see log below). I tried to wrap the output of "_rounds_count.count" into a table and then access the two variables but it doesn't seem to store the second value. Does anyone have an idea what I'm doing wrong? Any help would be greatly appreciated! shotcount = 0 rounds1 = 665 local _rounds_count = _unit1:getAmmo() for i = 1, #_rounds_count do rounds_test = env.info(_rounds_count[i].count) -- obsolete t = {(_rounds_count[i].count)} rounds_x = t[1] rounds_y = t[2] shotcount = (rounds1-rounds_x-rounds_y) trigger.action.outText("Shotcount: "..shotcount,10,false) end 2020-07-16 17:12:33.342 INFO SCRIPTING: 60 2020-07-16 17:12:33.342 INFO SCRIPTING: 263 2020-07-16 17:12:33.342 ERROR SCRIPTING: Error while handling event [string "C:\Users\Kirschi\AppData\Local\Temp\DCS\/~mis00003F44.lua"]:101: attempt to perform arithmetic on global 'rounds_y' (a nil value)
wraith70 Posted July 16, 2020 Posted July 16, 2020 Hey, I'm trying to use the Unit.getAmmo() function to check how many rounds a certain unit has fired. I was able to return the ammo count but it's two values for every gun seperately (see log below). I tried to wrap the output of "_rounds_count.count" into a table and then access the two variables but it doesn't seem to store the second value. Does anyone have an idea what I'm doing wrong? Any help would be greatly appreciated! shotcount = 0 rounds1 = 665 local _rounds_count = _unit1:getAmmo() for i = 1, #_rounds_count do rounds_test = env.info(_rounds_count[i].count) -- obsolete t = {(_rounds_count[i].count)} rounds_x = t[1] rounds_y = t[2] shotcount = (rounds1-rounds_x-rounds_y) trigger.action.outText("Shotcount: "..shotcount,10,false) end 2020-07-16 17:12:33.342 INFO SCRIPTING: 60 2020-07-16 17:12:33.342 INFO SCRIPTING: 263 2020-07-16 17:12:33.342 ERROR SCRIPTING: Error while handling event [string "C:\Users\Kirschi\AppData\Local\Temp\DCS\/~mis00003F44.lua"]:101: attempt to perform arithmetic on global 'rounds_y' (a nil value) I'm not an expert at this, but do table indexes start at 1? Past programming says it starts at 0 so hence t[0] and t[1] maybe??
HC_Official Posted July 16, 2020 Posted July 16, 2020 index start at 1 in lua No more pre-orders Click here for tutorials for using Virpil Hardware and Software Click here for Virpil Flight equipment dimensions and pictures. .
Grimes Posted July 16, 2020 Posted July 16, 2020 Which type of object are you checking? As far as I am aware the count value for all weapons is stored as a number for each individual weapon type and not as a table. I'd do it something like this: local rounds1 = 665 local count = 0 local _rounds_count = _unit1:getAmmo() for i = 1, #_rounds_count do if _rounds_count[i].desc and _rounds_count[i].desc.category == 0 then count = count + _rounds_count[i].count end end local shotcount = rounds1 - count The right man in the wrong place makes all the difference in the world. Current Projects: Grayflag Server, Scripting Wiki Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread) SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum
DonCalzone Posted July 16, 2020 Author Posted July 16, 2020 Which type of object are you checking? As far as I am aware the count value for all weapons is stored as a number for each individual weapon type and not as a table. I'd do it something like this: local rounds1 = 665 local count = 0 local _rounds_count = _unit1:getAmmo() for i = 1, #_rounds_count do if _rounds_count[i].desc and _rounds_count[i].desc.category == 0 then count = count + _rounds_count[i].count end end local shotcount = rounds1 - count Thanks a lot for your reply! Yes, I think the count value should be stored as numbers. I tried your code and it gives me some strange values like -226, -648, -1234 etc. the more i fire. I think I should've mentioned that I call this code through an eventhandler S_EVENT_SHOOTING_END. Anyway I tried to modify your code and went a step back, so to say, by trying to display the current ammo of every gun. I'm testing the code with a Bf-109 so it has the MG131 main guns and the MK108 cannon. When running the following code, it will display the ammo of the Mk108 in both lines instead of the MG131 ammo in the second line. So basically the problem remains that I don't know how to access the second value of "_rounds_count.count". local _rounds_count = _unit1:getAmmo() for i = 1, #_rounds_count do if _rounds_count[i].desc and _rounds_count[i].desc.category == 0 then count1 = _rounds_count[i].count end end for j = 2, #_rounds_count do if _rounds_count[j].desc and _rounds_count[j].desc.category == 0 then count2 = _rounds_count[j].count end end trigger.action.outText("Shotcount1: "..count1,10,false) trigger.action.outText("Shotcount2: "..count2,10,false) end i also tried various numbers like _rounds_count[j].desc.category = 1 but no success. Again, thanks for taking the time I really appreciate it.
Grimes Posted July 17, 2020 Posted July 17, 2020 https://github.com/mrSkortch/DCS-miscScripts/blob/master/ObjectDB/Aircraft/Bf-109K-4.lua The weapons part of that table is what the getAmmo() returns on a default BF-109. It doesn't return values for each gun, it just returns what is currently in the aircraft as a whole for each type of munition. As you can see it has 300 shells of 13mm HEI and 300 shells of 13mm APT, in addition to the single shell type that is in the 30mm. FYI, the for i = X, #whatever do, means that it is going to iterate that many times. So when iterating the size of a table and using i to check each index, then you are already counting for each weapon. So using the linked table above it would go to index 1, add the HEI shells, then index 2 to add the APT shells, and finally index 3 to add the 30mm shells. Having a second for j = 2, #_rounds_count do, just means it is going to add the at indexes 1, 2, 3, 2, 3 together. The category check refers to the weapon category as seen here: https://wiki.hoggitworld.com/view/DCS_Class_Weapon Shells = 0 So if you were checking it on an aircraft that had bombs, missiles, or rockets loaded that it wouldn't also count those munitions. I think the problem is due to how events specific work with guns. Each individual gun has its own shooting start and shooting stop event. On the P-51 for instance you'd get 6 events whenever you started shooting and 6 events when you ending shooting. The right man in the wrong place makes all the difference in the world. Current Projects: Grayflag Server, Scripting Wiki Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread) SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum
DonCalzone Posted July 17, 2020 Author Posted July 17, 2020 Thanks for the explanation, I deleted the for i = x part and wrote a seperate line for every index. It works like a charme but only until one of the guns has no rounds left. I tried to implement a simple check if an index returns nil or an empty table but I'm still getting an error about indexing a nil value when hitting 0. I also observed that sometimes the MG131 ammo is added up within the first index, but most of the time it's splitted the way you mentioned, the HEI shells in index 1, and APT in Index 2. When using env.info they will always be added up in the first line printed to the log. I suspect this has something to do with the SHOOTING_END eventhandler being fired twice because of the two guns but this shouldn't be an issue. The final code will be moved to an KILL eventhandler anyway. rounds1 = 680 count1 = 0 count2 = 0 count3 = 0 _rounds_count = {} -- probably obsolete, tried to apply code from a stackoverflow [url="https://stackoverflow.com/questions/50157721/assigning-subtables-to-unknown-indices-in-lua"]post[/url] _rounds_count[1] = {} _rounds_count[2] = {} _rounds_count[3] = {} if _unit == _unit1 then local _rounds_count = _unit1:getAmmo() if _rounds_count[1].count == nil or _rounds_count[1].count == '' then count1 = count1 * 0 else if _rounds_count[1].desc and _rounds_count[1].desc.category == 0 then count1 = _rounds_count[1].count end end if _rounds_count[2].count == nil or _rounds_count[2].count == '' then [b]-- Line 116[/b] count2 = count2 * 0 else if _rounds_count[2].desc and _rounds_count[2].desc.category == 0 then count2 = _rounds_count[2].count end end if _rounds_count[3].count == nil or _rounds_count[3].count == '' then [b]-- Line 125[/b] count3 = count3 * 0 else if _rounds_count[3].desc and _rounds_count[3].desc.category == 0 then count3 = _rounds_count[3].count end end trigger.action.outText("MG131 left: "..count1.. " rounds",10,false) trigger.action.outText("MG131 right: "..count2.. " rounds",10,false) trigger.action.outText("MK108: "..count3.. " rounds",10,false) end 2020-07-17 13:54:26.990 ERROR SCRIPTING: Error while handling event [string "C:\Users\Kirschi\AppData\Local\Temp\DCS\/~mis000005ED.lua"]:125: attempt to index field '?' (a nil value) 2020-07-17 13:54:51.422 WARNING LOG: 6 duplicate message(s) skipped. 2020-07-17 13:54:51.422 ERROR SCRIPTING: Error while handling event [string "C:\Users\Kirschi\AppData\Local\Temp\DCS\/~mis000005ED.lua"]:116: attempt to index field '?' (a nil value)
Grimes Posted July 17, 2020 Posted July 17, 2020 The state of getAmmo() changes based on the current contents. This can apply to every table in lua. Which means two things. 1. That the order in which things are returned isn't guaranteed to be the same. 2. That the number of table entries changes as munitions get depleted. Your code would need an extra check for the existence of an entry... if _rounds_count[3].count == nil ... If getAmmo() returned only two indexes, then whatever is at index 3 is nil. You will get an error if you check for a table entry of a non-existent index. if _rounds_count[3] and _rounds_count[3].count ... The right man in the wrong place makes all the difference in the world. Current Projects: Grayflag Server, Scripting Wiki Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread) SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum
DonCalzone Posted July 31, 2020 Author Posted July 31, 2020 Thanks a ton, Grimes! I ended up with following code, which works in general but I'm experiencing some performance drops. Gonna have to do some further testing with Eventhandlers. shotcount = 0 hitcount = 0 rounds1 = 665 count1 = 0 count2 = 0 count3 = 0 _rounds_count = {} _rounds_count[1] = {} _rounds_count[2] = {} _rounds_count[3] = {} function calculate_accuracy() local _unit1 = world.getPlayer() if _unit1:getAmmo() then local _rounds_count = _unit1:getAmmo() if _rounds_count[1] and _rounds_count[1].count then if _rounds_count[1].desc and _rounds_count[1].desc.category == 0 then count1 = _rounds_count[1].count end else count2 = count2 * 0 end if _rounds_count[2] and _rounds_count[2].count then if _rounds_count[2].desc and _rounds_count[2].desc.category == 0 then count2 = _rounds_count[2].count end else count2 = count2 * 0 end if _rounds_count[3] and _rounds_count[3].count then if _rounds_count[3].desc and _rounds_count[3].desc.category == 0 then count3 = _rounds_count[3].count end else count3 = count3 * 0 end shotcount = rounds1 - count1 - count2 - count3 accuracy1 = hitcount/shotcount*100 padded_accuracy = string.format("%02d", accuracy1) else count1 = count1 * 0 count2 = count2 * 0 count3 = count3 * 0 shotcount = rounds1 - count1 - count2 - count3 accuracy1 = hitcount/shotcount*100 padded_accuracy = string.format("%02d", accuracy1) end end
Recommended Posts