AKA_Clutter Posted September 19, 2024 Posted September 19, 2024 Hi all, I'm not a programmer and relatively new to lua and DCS MSE. I am not asking for someone to rewrite, or write the script, just point me in a direction, or explain to me why it is doing what it's doing. Als I will attach the full script at the end. At the end of the script is a comment section containing an outline of the script and what I think the flow is. I am trying to write a script that will display a F10Other menu to clients that enter a helo. They can choose one of two options that will give them the bearing and distance to a "hot Landing Zone". I use the scheduleFunction to repeat the message of distance and bearing every 20 seconds. So far I have only tested by myself. It seems to work up until the point I select another aircraft, or if I crash. FIRST ISSUE Once I leave the current unit, or crash, I get an error message about 20-30 seconds later stating the "unit does not exist". What confuses me is right before the line that the scripts crashes, I have a check to see if the unit is nill, if it is nill, then it isn't supposed to execute the line that crashes. I've attached a screenshot showing the error message and the related section of the script. The section of script is local function inFlightDistHead(tempTBL, time) local ourArgument = tempTBL[1] local uObject = tempTBL[2] local landingZone = tempTBL[3] local gID = tempTBL[4] -- add slight delay for multiplayer timing for i = 1, 333333333 do --[[ do nothing ]] end -- Simple error check if uObject == nil then trigger.action.outText(" Sorry, but uint object is nil",15) ourArgument= 1 -- trigger.action.outText("Unit life is ".. uObject:getLife(), 10) -- trigger.action.outTextForGroup(gID,"Inside schedule function ourArgument is " .. ourArgument.. ' and the landing zone is ' .. landingZone .. ' degrees', 10) elseif ourArgument == 53 and timer.getTime() < 1800 then trigger.action.outText("INSIDE LOOP: Unit life is ".. uObject:getLife(),10) -- THIS IS THE LINE TWHERE THE "UNIT DOES NOT EXIST OCCURS local cDistance, cHeading = distanceHeading(uObject, landingZone) trigger.action.outTextForGroup(gID, "Distance to " .. landingZone .. " is " .. cDistance.. ' nm at a heading of ' .. cHeading .. ' degrees', 10) trigger.action.outSoundForCoalition(2 , "shiny-sound-effect.ogg" ) -- Keep going AKA_Message_Output return (time + msgInterval) else -- That's it we're done looping trigger.action.outTextForGroup(gID, '\n===========================\nMaximum time exceeded\nMax time was set to 1800 \n===========================\n', 10) return nil end end -- "end' assocaited iwth inFlightDistHead(tempTBL, time) Now, I tried to get fancy and this function is inside other function that I set up as an overarching function/wrapper. I don't know if that could cause this issue or not due to something being out of scope? SECOND ISSUE I am trying to use the world.eventHandler to see if I can tell when a unit has been exited. I have added S_EVENT_PLAYER_LEFT tas a check, but I don't seem to get that activated when I leave an aircraft. In the section of code below, I DO get the debug message when I crash but not when I just choose a different slot. elseif ((event.id == world.event.S_EVENT_EJECTION and event.initiator ~= nil) or (event.id == world.event.S_EVENT_PILOT_DEAD and event.initiator ~= nil) or (event.id == world.event.S_EVENT_CRASH and event.initiator ~= nil) or (event.id == world.event.S_EVENT_PLAYER_LEFT and event.initiator ~= nil) or -- added to mine, not in Relent's S_EVENT_UNIT_LOST (event.id == world.event.S_EVENT_UNIT_LOST and event.initiator ~= nil) or -- added to mine, not in Relent's S_EVENT_UNIT_LOST (event.id == world.event.S_EVENT_DEAD and event.initiator ~= nil)) then local leftUnit = event.initiator if (debugFlagHotLZ == 1) then trigger.action.outText("leftUnit loop Event ID is = " .. event.id,5) end Thanks in advance for any and all help. null Hot_LZ_Challenge_v0_19.lua ---------------- AKA_Clutter Win 10 Pro, Intel i7 12700k @4.6 GHz, EVGA RTX 3080 FTW, Ultra 64 GB G.Skill DDR4 3600 RAM, Acer 27" flat screen, HP Reverb G2, TM Warthog HOTAS with Virpil warBRD base, MFG Rudder Pedals, Virpil TCS Rotor Base with AH-64Dcollective, TrackIR 5 Pro w/Vector Expansion, PointCTRL.
Solution cfrag Posted September 20, 2024 Solution Posted September 20, 2024 (edited) 13 hours ago, AKA_Clutter said: FIRST ISSUE Once I leave the current unit, or crash, I get an error message about 20-30 seconds later stating the "unit does not exist". Ah, the joys of DCS, mixed with one's own expectations. You already have all the pieces of the puzzle, and I think that you implicitly believe that one thing means the other (in a perfect world it would, but not Lua/DCS). Let's go through the the steps one by one. You enter your aircraft "Crasher" and depart. A status display call is scheduled in 20 seconds with a reference to your unit "Crasher". In computing terms, a 'reference' points to the memory location that contains data, here the data for unit "Crasher" One second later you crash your aircraft "Crasher" and it is removed from the game. The memory for that unit is freed - made available for other purposes. Your reference to "Crasher" still points to the memory location formerly assigned to "Crasher". 19 seconds later, your scheduled status display function is invoked. As part of the params that are retained is a reference to the (now crashed and invalidated) unit "Crasher" in uObject. Your code checks if uObject == nil. Your reference to "Crasher" STILL points to to the memory location that formerly contained the (now deleted) unit, meaning it is not nil, so the check correctly fails in Line 395 you now access uObject's method getLife() member via "uObject:getLife()". Unfortunately, uObject is no longer a valid object, and you get the "Unit doesn't exits" error So this is correct. A reference to a unit isn't nilled when the unit is destroyed, and a nilcheck to a cached unit (a saved unit reference) will not save you from this. So, how do you protect against that? Many ways, one is to save the unit's name instead, and directly retrieve the unit by name before you try to access it: uObject = Unit.getByName(uName) if not uObject then trigger.action.outText("Sorry, but unit object is nil",15) -- some spelling corrected return end Edited September 20, 2024 by cfrag 2
cfrag Posted September 20, 2024 Posted September 20, 2024 13 hours ago, AKA_Clutter said: SECOND ISSUE I am trying to use the world.eventHandler to see if I can tell when a unit has been exited. I have added S_EVENT_PLAYER_LEFT tas a check, but I don't seem to get that activated DCS's event API is a cruel joke on us mission creators. That event ID is only invoked every second blue moon for players who have two children or less and can't be relied upon. 3
AKA_Clutter Posted September 20, 2024 Author Posted September 20, 2024 @cfrag See I told you I was a noob at programming/lua/DCS MSE Thanks once again. Issue 1 2 hours ago, cfrag said: Ah, the joys of DCS, mixed with one's own expectations. You already have all the pieces of the puzzle, and I think that you implicitly believe that one thing means the other (in a perfect world it would, but not Lua/DCS). Let's go through the the steps one by one. ... ... ... Your code checks if uObject == nil. Your reference to "Crasher" STILL points to to the memory location that formerly contained the (now deleted) unit, meaning it is not nil, so the check correctly fails ... So this is correct. A reference to a unit isn't nilled when the unit is destroyed, and a nilcheck to a cached unit (a saved unit reference) will not save you from this. So, how do you protect against that? Many ways, one is to save the unit's name instead, and directly retrieve the unit by name before you try to access it: Yeap, I wasn't thinking in programing terms in that "=" isn't equal but "assign". programing 101. And I will try other ways to protect against this. As I have it, I could use the group ID in a similar fashion , but that would only work with 1 unit per group. 2 hours ago, cfrag said: DCS's event API is a cruel joke on us mission creators. That event ID is only invoked every second blue moon for players who have two children or less and can't be relied upon. I thought it might be something like this. DCS MSE has many dead-end rabbit holes, or so I have read. Thanks again for the help. Now to go update the script. ---------------- AKA_Clutter Win 10 Pro, Intel i7 12700k @4.6 GHz, EVGA RTX 3080 FTW, Ultra 64 GB G.Skill DDR4 3600 RAM, Acer 27" flat screen, HP Reverb G2, TM Warthog HOTAS with Virpil warBRD base, MFG Rudder Pedals, Virpil TCS Rotor Base with AH-64Dcollective, TrackIR 5 Pro w/Vector Expansion, PointCTRL.
Recommended Posts