dafydd99 Posted February 16 Share Posted February 16 (edited) I've made a simple stone tablet to 'display' numerals which can change over time. It can display one of ten numerals, so I'm using 'placeAtMe' to put that item in place. The numerals are statics and have no collision, just a few BSTriShape's. function setNumber(int numeral) Debug.Trace("Setting number to:"+numeral) ObjectReference newNumeral=placeAtMe(NumeralsList.GetAt(numeral) as form, 1, true, true) newNumeral.SetScale(numeralScale) newNumeral.enableNoWait() if(!newNumeral.is3DLoaded()) Debug.Trace("3D NOT loaded") endif endfunction This works around 99 times out of 100. But just once in a while it doesn't. It believes it has made a new objectreference, and it believes the 3d has been loaded, but no object is visible. Anyone got any thoughts about this? I had thought that putting a slight delay (utility.wait(0.1)) between the setscale and enablenowait fixed it, but alas no. Thanks in advance for any help. Cheers - dafydd99 Edited February 18 by dafydd99 Link to comment Share on other sites More sharing options...
greyday01 Posted February 19 Share Posted February 19 I wouldn't use place at me. I would simply put all the numerals in place but disabled. Use a script to enable the one you want and disable all the rest. You could put them in a form list and use that to disable and enable them. Link to comment Share on other sites More sharing options...
PeterMartyr Posted February 23 Share Posted February 23 No, it is your code, there is so many things wrong with it, I do not know where to start, which is why coders have not replied to you)) But a quick fix is Use a Global instead local variable in the function Use a loop with a set alliterations to avoid a infinite loop with is3DLoaded, incase the object 3D is tardy in loading Delete the newNumeral Object when it save to do so, that mean when it unloads OFC that open a rabbit hole, of other things, that your code is missing)) like what happen if it is call twice before it unloads? Maybe the check should be at start, to handle it, and have faith place at me works, which it does Link to comment Share on other sites More sharing options...
xkkmEl Posted February 23 Share Posted February 23 I too was thinking that your numerals don't show because they get hidden by other numerals that are being piled up. Remembering the last numeral created, and deleting it when creating a new one... Dunno about using a Global though; can't put an ObjectReference into that; use a script variable, outside the event/function declaration, to remember last numeral created. Dunno what loop PeterMartyr is thinking of either. ObjectReference newNumeral = None function setNumber(int numeral) Debug.Trace("Setting number to:"+numeral) if newNumeral newNumeral.delete() endif newNumeral=placeAtMe(NumeralsList.GetAt(numeral) as form, 1, true, true) newNumeral.SetScale(numeralScale) newNumeral.enableNoWait() endfunction You may need to cleanup your current savefile, or start a new game, to get rid of the extra numerals you already created. Link to comment Share on other sites More sharing options...
dafydd99 Posted February 24 Author Share Posted February 24 On 2/19/2025 at 7:10 PM, greyday01 said: I wouldn't use place at me. I would simply put all the numerals in place but disabled. Use a script to enable the one you want and disable all the rest. You could put them in a form list and use that to disable and enable them. Thanks greyday01 - yes your suggestion should be the most reliable, and might end up being necessary. I was hoping not to need to place eleven objects for just one function - but perhaps it's unavoidable. Link to comment Share on other sites More sharing options...
dafydd99 Posted February 24 Author Share Posted February 24 On 2/23/2025 at 11:40 AM, PeterMartyr said: No, it is your code, there is so many things wrong with it, I do not know where to start, which is why coders have not replied to you)) But a quick fix is Use a Global instead local variable in the function Use a loop with a set alliterations to avoid a infinite loop with is3DLoaded, incase the object 3D is tardy in loading Delete the newNumeral Object when it save to do so, that mean when it unloads OFC that open a rabbit hole, of other things, that your code is missing)) like what happen if it is call twice before it unloads? Maybe the check should be at start, to handle it, and have faith place at me works, which it does Thanks for the response PeterMartyr. No - that isn't my complete code, it's a simplified snippet to just show the important parts about the placeAtMe - to reply to your points... yes a script-level variable is used to hold the current numeral. The newNumeral variable above is temporarily used to enable the numeral, then the old one is disabled (deleted and dereferenced to allow the engine to complete the deletion) - this avoids the slight 'flash' that can appear, and removes the previous numeral permanently. the code above is to point out that the numeral BELIEVES it has had the 3DLoaded, where as it hasn't actually appeared - so it is not necessary to iterate a few times to check. the creation of a numeral is done within a 'busy' state which blocks out any other attempts to create a new numeral until it has completed - so we shouldn't be dealing with a race condition. In the busy state it would also be logged if an attempt is made to setNumber() again, and that's not happening. Link to comment Share on other sites More sharing options...
dafydd99 Posted February 24 Author Share Posted February 24 (edited) On 2/23/2025 at 12:39 PM, xkkmEl said: I too was thinking that your numerals don't show because they get hidden by other numerals that are being piled up. Remembering the last numeral created, and deleting it when creating a new one... Dunno about using a Global though; can't put an ObjectReference into that; use a script variable, outside the event/function declaration, to remember last numeral created. Dunno what loop PeterMartyr is thinking of either. ObjectReference newNumeral = None function setNumber(int numeral) Debug.Trace("Setting number to:"+numeral) if newNumeral newNumeral.delete() endif newNumeral=placeAtMe(NumeralsList.GetAt(numeral) as form, 1, true, true) newNumeral.SetScale(numeralScale) newNumeral.enableNoWait() endfunction You may need to cleanup your current savefile, or start a new game, to get rid of the extra numerals you already created. Thanks xkkmEl. Hmm. Doesn't seem to due to piled up numerals - it can be changed 20 times in a row with no problems, then is missing, and then works again fine for another 20 times. Yes, sorry - as discussed above in the reply to PeterMartyr this is only a snippet from a more complex script. The reason we have the newNumeral as a local variable is because it is temporary, and a script level ObjectReference called 'currentNumeral' is used to handle the 'old' numeral until the new numeral can take over. It is kept alive until slightly after the new numeral is created and the 3d is loaded to avoid a 'flash'. I think by 'Global' he's refering to the variable scope, and just means not local to the function, ie a script-level variable as you've given above. I'm thinking at the moment it could be the engine getting overloaded by something and bailing in those instances. Or could be something unreliable in the settings of the nif. Or potentially there's something unexpected going on in the threads that I've missed. I'll try to do some more extensive testing on just the placeAtMe part. EDIT: btw, yes, I'm starting with a clean save file without the mod just in case, and yes there's actually some belts and braces code that clears out any numeral that might be placed there but the reference has somehow been lost using Game.FindClosestReferenceOfAnyTypeInListFromRef() Edited February 24 by dafydd99 Link to comment Share on other sites More sharing options...
dafydd99 Posted February 24 Author Share Posted February 24 Okay - more testing but I'm still as baffled as before. When a numeral doesn't appear (again very rarely - like 1/100) it still passes the tests of... is3DLoaded() TRUE isDisabled() FALSE So on finding a broken numeral, I travelled away to unload all cells, and returned with an onload() test on the tablet that references this created numeral. One of two things happened... 1) it appeared correctly. No sign as to why it hadn't before, but was working as it should. This would also happen on save then load. 2) the 3d did not load. A check on the reference showed that yes, there was an object there and it had the correct base object form id. It was however disabled. On enabling it did not appear, but isDisabled() returned false. Travelling away again and returning, and it was in a disabled state again. It's still as if just once in a while it creates a duff reference. Unfortunately as all the tests return positive at the time of creation, it's hard to catch and fix. Perhaps I need to make a save with a duff reference and analyse the save more closely. Link to comment Share on other sites More sharing options...
PeterMartyr Posted February 26 Share Posted February 26 Post the actual code if you really want help, we cannot help fix it if ain't broken.. so to speak. No good you posting it does not work. Honestly I am inclined to think it is your states causing the problem, maybe, I cannot see the code Link to comment Share on other sites More sharing options...
dafydd99 Posted Thursday at 02:48 AM Author Share Posted Thursday at 02:48 AM Okay - finally think I've managed to isolate the bugs, and there seem to be two of them: The first bug is quite serious but perhaps understandable - placeAtMe was probably never intended to be used this way. If you use placeAtMe to place a new reference in a cell that is not currently loaded, it appears to have a small chance of creating a corrupt reference. I was using this to set a numeral during initialisation (after a random wait to avoid over stressing the scripting engine). A simple fix for this is to instead run it within an onload() - puts slightly more work to the scripting engine at cell load, but should still be okay. The second bug was very hard to track down. The locations I was placing the numeral were within Room Markers (roombounds). The pivot points of the new references were well within the bounds of the room marker, and PlaceAtMe usually handles this just fine and correctly applies it to the room marker it's been placed in - but once in a very rare while it doesn't, and the new reference is placed in the default room bound - ie outside all the room markers. So obviously it exists (hence passing all tests), but it's not visibile from within that room marker! However, 'tcling' outside the room marker makes all the references inside the room marker disappear as you would expect, and the faulty references appear. Clearly on a game load, this is rechecked and they appear again correctly. Not really sure how to fix this without removing room markers - which will obviously cause optimisation issues. There doesn't seem to any mechanism to force a new reference to a room marker. All I can think is that perhaps there might be a flag on the nif, or potentially something else I'm missing that might somehow be able to avoid it? Or some mechanism to force a reference to be rendered no matter which roombound it appears in. Does anyone have any wisdom to share? Potentially the areas containing my numerals could be forced into the default room bound at a cost to performance to sidestep this bug. Cheers - dafydd99 Link to comment Share on other sites More sharing options...
Recommended Posts