Schismatrix Posted November 28, 2023 Posted November 28, 2023 I swear to Zeus this is killing me.. I have tried setting up an event handler to take certain actions when a unit dies, but is constantly running in to bugs. I have tried DEAD, KILL, UNIT_LOST and BDA with similar issues of initiator and target randomly not having any values (returning nil even though it should be there). In testing it seems BDA is the least likely one to throw errors. My suspicion is that since it is evaluated faster than DEAD and UNIT_LOST, it may get in and grab the values before they are removed from the table in memory.. Below is an example of what I am trying to do at the moment: local unitReport = {} local _mrkID = 1000 function unitReport:onEvent(event) if (world.event.S_EVENT_BDA == event.id) then local _objectSide = event.target:getCoalition() local _deadUnitName = event.target:getName() local enmyPt = event.initiator:getPoint() --buggy line local _enmyType = event.initiator:getTypeName() local _enmyWPN = event.weapon:getTypeName() if _objectSide == 2 then trigger.action.outText(_deadUnitName..' is hit!', 2) _spottingChance = math.random(1,10) if _spottingChance > 6 then trigger.action.markToCoalition(_mrkID,'enemy contact: '.._enmyType,enmyPt,2,false) _mrkID = _mrkID + 1 end end end end and attached is the error I'm getting. I have also experienced similar nil value issues when trying to access the killed unit, as if the program already forgot it was there.. Any help would be hot!
Schismatrix Posted November 29, 2023 Author Posted November 29, 2023 So I did a bit more testing. My suspicions about the game dumping the event information too rapidly seems to be correct. Once I put in a condition to check whether the event values were actually populated, the errors seem to have stopped. Code looks like this now, with added code in bold: function unitReport:onEvent(event) if (world.event.S_EVENT_BDA == event.id) then if event.target ~= nil and event.initiator ~= nil then --check if event data is present local _objectSide = event.target:getCoalition() local _deadUnitName = event.target:getName() local _deadUnitCat = event.target:getCategory() local _enmyPt = event.initiator:getPoint() local _enmyType = event.initiator:getTypeName() if _objectSide == 2 and _deadUnitCat == 2 then trigger.action.outText(_deadUnitName..' is hit!', 2) local _spottingChance = math.random(1,10) if _spottingChance > 5 then trigger.action.markToCoalition(_mrkID,'enemy contact: '.._enmyType,_enmyPt,2,false) _mrkID = _mrkID + 1 end end end elseif (world.event.S_EVENT_CRASH == event.id) then if event.initiator ~= nil then --check if event data is present local _objectSide = event.initiator:getCoalition() local _crashedUnitName = event.initiator:getName() local _crashPt = event.initiator:getPoint() if _objectSide == 2 then trigger.action.outText(_crashedUnitName..' is down!', 2) trigger.action.markToCoalition(_mrkID,_crashedUnitName..' crash site',_crashPt,2,false) _mrkID = _mrkID + 1 end end end end
Solution cfrag Posted November 29, 2023 Solution Posted November 29, 2023 I agree that it would be prudent to apply some sanity checks at the very beginning of your event processor: function unitReport:onEvent(event) if not event then return end -- wtf? bad call if not event.initiator then return end -- no initiator, no interest ... (some more test before you dereference them) ... if not event.target then return end end That way, your code won't scream at you when it receives something unexpected (for example, when at a event.dead invocation, a formerly unit object got sneakily converted to a static object and now crashes on getCoalition() and similar fun. Yeah, that can now happen when the unit 'cooks off'. Fun with events.) -ch
Recommended Posts