DrakeTheDragon Posted February 4, 2018 Share Posted February 4, 2018 Any idea why this particular line is able to break a while loop/script? if rTarget != player && rTarget.GetInSameCell PlayerRef It's inside a simple "while" loop: let iSize := ar_Size arSomeArray let iIndex := 0 While (iIndex < iSize) let rTarget := arSomeArray[iIndex]["actor"] if rTarget != player && rTarget.GetInSameCell PlayerRef ;do something endif let iIndex += 1 Loop "arSomeArray" is a simple Array (0-N) containing StringMaps with data and stats about certain actors, like the player, and index "actor" contains a reference to the actor itself.At the time of testing this code said array contains 3 elements, the player and 2 companions (NPCs). The loop should skip the player, only handle companions, and also only those who are in the same cell as the player. I added debug outputs before every line of code, and this particular line in question is where everything stops. Neither does the loop continue beyond index 0, nor does the Quest script run another time. (It's set to repeat after 0.1s delay.)When I call "Player.GetInSameCell PlayerRef" inside the game's console, it correctly returns "1", so it shouldn't be the fact that it's run on the player here that makes it break.And it even breaks completely silent without any sign. If I hadn't spiked the code with 1 debug output per line, I'd never have even noticed it actually broke. When I re-write the check like so, everything works fine: if rTarget == player let iIndex += 1 Continue elseif 0 == rTarget.GetInSameCell PlayerRef let iIndex += 1 Continue else ;do something endif So I'm not searching for a solution here. I'm just wondering if anybody has any idea as to why it even breaks to begin with.Should it have to do with the &&-ing inside the "if"? Or is it calling "GetInSameCell" from "Player" with "PlayerRef" that's breaking here? But if so, then why does it work inside the console? I'm really curious to know why this particular line would just silently break the script. Interesting side-observation: Despite the function reference and WiKi page saying "GetInSameCell Player" would be a fine use of the function, in my CSE the line with this parameter won't even compile. It had to be substituted by "PlayerRef" first for the compiler to even proceed. Link to comment Share on other sites More sharing options...
lubronbrons Posted February 4, 2018 Share Posted February 4, 2018 (edited) hello Drake,I recognized this problem is null pointer or base object reference issueyou said arSomeArray is data and stats about certain actorsthis is a fact... somehow we just can't access some dynamic actor (index FF / created in-game) if they are NOT loaded into memoryso you should put some validation before do something with it or the script could go break & stop working,don't use unreliable syntax IsFormValid, the best way to do that from my experience is by using GetObjectTypealsoyou should make sure data stored in arSomeArray[XXX]["actor"] is REFERENCE not base object, because if we call syntax GetInSameCell upon base object the script will stop working toothis is my suggestion for your solution let iSize := ar_Size arSomeArray While (iSize -= 1) >= 0 let rTarget := arSomeArray[iSize]["actor"] if GetObjectType rTarget if IsReference rTarget if rTarget.GetInSameCell PlayerRef ;make sure this is REF not BASE OBJECT if rTarget != PlayerRef ;do something endif endif endif endif Loop EDIT : make a slight chance to script added one more validation, I think I know where is the real problem in your script. maybe when you assign pc to arSomeArray you used Player? that is base object, Player form ID is 7 and PlayerRef form ID is 14. Player is base object, while PlayerRef is reference. in your case maybe Player.GetInSameCell PlayerRef halt your script because the data stored in arSomeArray is Player (use PlayerRef instead)that command works in console because I heard that game engine try to translate it to PlayerRef, but... will not work on some script (usually event handler) Edited February 4, 2018 by lubronbrons Link to comment Share on other sites More sharing options...
QQuix Posted February 4, 2018 Share Posted February 4, 2018 I noticed two things: 1. Player x PlayerRef Long time ago scruggs explained to me that, whenever it finds the word 'Player', the compiler tries to make an 'intelligent' decision whether it means the player base object or the player reference. He elaborated but i don't remember the details. I remember that I had lost many hours debugging a code and I swore I would never use 'Player' again in my scripts (unless, of course, I needed the Player base object). I took the opportunity to mention this, but I dont really think this is your problem. After all the player base object is just a ref var and, if the compiler used the player base object, the comparison would just be 'not true' and not break the code. 2. Operator precedence One possibility is that the compiler is interpreting you code as: " if rTarget != ( player && rTarget.GetInSameCell PlayerRef) " Try " if ( rTarget != player ) && rTarget.GetInSameCell PlayerRef " Or maybe eval has a better parsing: if eval rTarget != player && rTarget.GetInSameCell PlayerRef Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted February 4, 2018 Author Share Posted February 4, 2018 Hmm, interesting feedback. @lubronbrons: Yes, I'm manually inserting "player" as the first actor into the array. The companions are inserted from a regularly repeated GetFirstRef and GetNextRef loop in another script, unless already found inside, to keep the list of "party" members up-to-date. So, if I got this right, the loop shouldn't break at a point later on, provided I prevent it from running GetInSameCell on the player part. I could easily switch the "player" actor over to "PlayerRef" as well, but I'm not exactly using the "actor" part from inside the array for anything else much anyways. I may be printing out its "name" into a HUD element going along with the entry, but that one's working for both types anyways. I'm not sure I need further validation of what's inside "actor", because the script inserting the entries already takes care only valid ones go inside. But it can't hurt being extra-cautious either. If all else fails, I should also be able to just call the GetInSameCell on the player instead and check for where the actor is. The player will always be defined, loaded into memory and running on high priority, so those calls shouldn't be able to break. Unless, of course, using an unloaded reference as the comparison parameter can also break the call. :ermm: I'll watch out for further breaking throughout my testings now, but so far, like I said, the script does no longer break after the fix I mentioned, so calling GetInSameCell seems to work fine now on all my current companions, and they're gone poof to random unknown to me places right now due to background quests manipulating them. Famous companion mod quest spoiler: - Viconia De'Vir's suddenly disappeared after a certain night, complete with a quest log entry explaining it and a new quest to go find her again. But she's still inside my list, and I can check for her being inside the same cell as me or not without it breaking.- A short-time temporary companion from another mod was left behind in a house introduced by said mod watching after the place, after I finished the quest that was introduced by said mod with him by my side. And again, the script is still checking if he's near me or not without breaking. Whenever I get near them again, the HUD elements displaying their custom stats will immediately pop up again just fine. This part seems to work quite flawlessly so far. When I add another companion into the player faction, this one, too, will have a HUD element pop right up, until I leave him be somewhere else and move away too far, then the element will disappear again, just like it should be. No further breaking here at any point so far. But I'll keep a closer watch now, thanks. @QQuix: Oh, yeah, operator precedence, that could definitely be another explanation for it. I recall having to encapsulate individual comparisons inside brackets before AND-ing or OR-ing them in all my previous scripts as well for some reason, not just for visibility's sake. Don't know why I didn't do it as well this time. After all it regularly turned out to be quite inevitable in the past. Link to comment Share on other sites More sharing options...
lubronbrons Posted February 4, 2018 Share Posted February 4, 2018 it's always interesting to help others regarding scripting for me,as long as I still understand the scope of it I will try to helpbecause in the process usually I learn something new too~ Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted February 4, 2018 Author Share Posted February 4, 2018 Oh, yeah, this "learning something new" part is likely about the main reason I'm still hanging out here. I may be a member on the Nexus since way longer than the site itself exists (I was a member already on its predecessor, and my account was automatically migrated over when it launched. My "member since" date is misleading, as it's from when Buddha changed my username, not from when I actually joined. ^^), but I, too, am always learning something new almost every day on here. :happy: Link to comment Share on other sites More sharing options...
Moktah Posted February 5, 2018 Share Posted February 5, 2018 (edited) brain is so muddied up right now.... not sure why I'm trying to tackle a new problem.speaking of which... not sure if you've found a solution yet. for what its worth if rTarget != player && rTarget.GetInSameCell PlayerRef looks like it needs to be broke down into two If statements if rTarget != playerif rtarget.getinsamecell playerref;do stuffendifendif if that first reference is EVER the player itselfthen its the same as sayingif player.getinsamecell playerref it no like that when you use the && within an if statement.... it looks at both sides of the && even if the first side is FALSE Edited February 5, 2018 by Moktah Link to comment Share on other sites More sharing options...
lubronbrons Posted February 5, 2018 Share Posted February 5, 2018 speaking of which... not sure if you've found a solution yet. he did solve itquote : "I'll watch out for further breaking throughout my testings now, but so far, like I said, the script does no longer break after the fix I mentioned, so calling GetInSameCell seems to work fine now on all my current companions, and they're gone poof to random unknown to me places right now due to background quests manipulating them." Link to comment Share on other sites More sharing options...
Moktah Posted February 5, 2018 Share Posted February 5, 2018 Sweet Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted February 5, 2018 Author Share Posted February 5, 2018 Yeah, I actually found a working solution already before I even created the topic. Like I said in the OP, I'm not exactly searching for a solution here, but thought I'd share the observed problem together with my fix in an attempt to figure out what might be causing it to begin with, as it is a very unusual observed behavior after all, the script itself just silently breaking without even a runtime error or some such being thrown, and me first of all having had to figure out it even broke to begin with. Sorry, if my lengthy introduction got a little confusing about that part. I usually write too much. :sweat: But this discussion and exchange of knowledge has already helped quite a lot in other regards, as it always does. Yes, you're right, that's how conditions in ObScript are processed, every part first, then their logical combination. In different programming languages it's done differently, in C(++), PHP or JavaScript for example (if I'm not mistaken about one or more of those after all the years of programming in them) conditions are usually evaluated from left to right, and as soon as it hits a "false", everything thereafter won't be looked at. You can effectively prevent calls on undefined structures by simply prefixing the condition with an AND-ed check for the structure not to be undefined. Not so in ObScript unfortunately. QQuix input reminding me how important it is in ObScript to wrap individual conditions into brackets, especially when they're function calls, before logically combining them, has by now also been re-introduced into every single combined condition I found where I somehow mysteriously still missed it. I really should've known better from all those years of experience, but I'm afraid to admit my lengthy periods of inactivity in my modding projects apparently have even made my scripting habits become a little "rusty" by now. *sigh* And lubronbrons' list of prerequisite checks of the reference variable used, before doing any of those function calls I intend, has by now also been introduced into yet more pre-emptive conditions to "continue" the loop before proceeding to the problematic parts of code inside. It's now not only the 2 checks already given in the OP, but GetObjectType and IsReference is now checked as well, and all 4 in the right order to prevent any potentially troublesome checks from even running by coming later. Thanks, you all, for the input provided! It's definitely not gone wasted. :happy: Link to comment Share on other sites More sharing options...
Recommended Posts