Guest tomm434 Posted May 26, 2014 Posted May 26, 2014 If you haven't already, you should check out Doc's tuts. They're in his sig. He's got GREAT tuts. *obnoxious over-the-top wink* Actually I did it the moment I started scripting. They are very very helpful indeed.
Halstrom Posted May 28, 2014 Author Posted May 28, 2014 Hmm just found an interesting one 3 of my scripts all similar seem to have got corrupted or saved wrong somehow in GECK. I haven't updated GECK or Powerup for ages so it's not the recent PU update. When I opened these 3 similar scripts that I haven't worked on for a long time and tried to resave/compile them I got the same error in all 3. And "&&" seemed to have disappeared and also an "if condition" line had disappeared leaving an extra "endif" when I tried to save. Which is nuts as I shouldn't have been able to save them like that. Now it get's weirder I reopened the scripts after saving and the script is slightly different to what I saved and seems like a better/later version, it's like somehow I must have opened an old corrupt backup the first time.
nyaalich Posted May 28, 2014 Posted May 28, 2014 Xilandro, on 28 May 2014 - 01:20 AM, said Also, after player.setscale <value> always use player.disable player.enable It will fix fps drop. Yes, there is fps drop after setscale. Because it's vanilla bug. Has anyone else heard of player.setscale causing an fps issue?
prideslayer Posted May 28, 2014 Posted May 28, 2014 I haven't, but I've never used it on the player either. The only thing sexout scales are bighorners.
Odessa Posted May 28, 2014 Posted May 28, 2014 As may have been implied from previous posts, I've been battering NVSE 4 with compiler override to see when it caves. A little additional insight: This line: if eval ( ((rTrickJohn.GetIsSex "Female") && (sex_type == "Vaginal" || sex_type == "Anal")) || (sex_type == "Peg") ) Causes my script to eat itself and never run again, every time (~15) I've tested it. Adding in extra 'evals' (and/or parentheses) for each clause makes no difference, such as: if eval ( eval (rTrickJohn.GetIsSex "Female") && (eval (sex_type == "Vaginal") || eval (sex_type == "Anal")) ) || eval (sex_type == "Peg") ; or (amongst others): if eval ( (eval rTrickJohn.GetIsSex "Female") && ((eval sex_type == "Vaginal") || (eval sex_type == "Anal")) ) || (eval sex_type == "Peg") But If I cut the line down to either: if eval (rTrickJohn.GetIsSex "Female") ; or if eval ( (sex_type == "Vaginal" || sex_type == "Anal") || (sex_type == "Peg") ) Then everything is peachy. So, as has already been suggested by a few people, trying to do too many things in one 'if eval' line is dangerous. The feeling I get is that 'if eval' statements are more sensitive than other lines, my scripts are doing CO stuff all over the place in regular lines and its (so far...) otherwise been reliable, even with 4 nested function calls on one line. But: foreach iter <- (ar_List PlayerREF, SexoutSolJennyREF, SexoutSolMaidaREF, SexoutSolGerdaREF) This has always worked the first time the script runs it, but it once generated an NVSE error in the console the second. Not an exhaustive analysis, but using a temp array variable in a foreach may be safer. ....Well, if I say so myself, my script is mental (it is otherwise reliable.. so far). Special thanks to everyone who made UDF, arrays, strings + NX possible. scn SexoutSolHeliosOneQuestScript ; ** Helios One Festivities ; * Uses Globals: True, False, NONE, NOTFOUND := 1, 0, 0, -1 float fDate int iStage array_var aGirls array_var aJohns array_var aTemp array_var iter array_var nestiter array_var aGirlIdles ref rGirl int iOffset int iCount ref rJohn ref rBoxJohn int iTricks int iBoxTricks int iBoxStage ref rBoxedBitch int iScannerStage int SexType ref rTrickGirl ref rTrickJohn int SubTrick ref rItem int iDuration string_var sex_type array_var mn ; * magic numbers int IsValid Begin _GameMode DebugPrint "Sol HOQ %g %g" iStage, iBoxStage ; ** Init if iStage == 0 let mn := sol.aMagicNumber ; * Furniture - do enable once if fDate == 0 let iCount := ListGetCount SexoutSolHeliosFurnitureFL while iCount > 0 let iCount -= 1 let rItem := ListGetNthForm SexoutSolHeliosFurnitureFL, iCount rItem.Enable loop endif let fDate := GameDaysPassed ForceWeather SexoutSolHeliosPartyWeather let sex_type := "Any" let SexoutSolNovacQuest.HeliosParty := False ; * For Dunton dialog let aGirlIdles := ar_List "DukovDrinkStand01", "LooseLookingAround", "LoosePointAtSelf", "SpecialIdleNVTapDance", "LooseDanceFemFidget05", "LooseDanceFemFidget03" let aTemp := ar_List PlayerREF, SexoutSolJennyREF, SexoutSolMaidaREF, SexoutSolGerdaREF let aGirls := ar_Construct "array" let iOffset := 0 foreach iter <- aTemp ;(ar_List PlayerREF, SexoutSolJennyREF, SexoutSolMaidaREF, SexoutSolGerdaREF) let rGirl := iter["value"] if rGirl.GetDead continue elseif rGirl.GetDisabled rGirl.Enable endif ar_Append aGirls, rGirl rGirl.NX_SetEVFl "Sol:Busy", False rGirl.MoveTo SexoutSolHeliosOneSTART, iOffset, (Rand 0, 50) let iOffset += 100 loop let aTemp := ar_Null let iOffset := 0 ; * Johns let iCount := ListGetCount SexoutSolNovacNCRJohnsFL while iCount > 0 let iCount -= 1 let rJohn := (ListGetNthForm SexoutSolNovacNCRJohnsFL, iCount) if eval !(rJohn.GetDead) rJohn.NX_SetEVFl "Sol:NextSex", 0 rJohn.MoveTo SexoutSolHeliosOneJohnStart, iOffset, (Rand 0, 50) let iOffset += 50 endif loop ; * Idle Markers let iCount := ListGetCount SexoutSolHeliosIdleMarkersFL while iCount > 0 let iCount -= 1 let rItem := ListGetNthForm SexoutSolHeliosIdleMarkersFL, iCount rItem.Enable loop SexoutSolWallaceREF.Enable SexoutSolWallaceREF.MoveTo SexoutSolWallaceSTART SexoutSolHeliosZAZBox.Enable let iBoxStage := 0 let rBoxedBitch := NONE PlayerREF.NX_SetEVFl "SO:NotNow", True let iStage := 1 DebugPrint "Sol: HOQ - Done init part 1" return elseif iStage == 1 ; * Invite any local NCR and companions if PlayerREF.IsInInterior ; * if the moveto hasnt happened yet return endif let aJohns := ar_Construct "array" let rJohn := GetFirstRef mn["Actor"], 2 while rJohn != NONE if eval (Call tsolIsValidSexActor rJohn) if eval (ListGetFormIndex SexoutSLDataCurrCompanionsFem, rJohn) != NOTFOUND ar_Append aGirls, rJohn elseif eval (rJohn.GetInFaction NCRFactionNV) || (rJohn.GetPlayerTeammate) ar_Append aJohns, rJohn rJohn.AddScriptPackage SexoutSolHeliosOnePKG rJohn.evp endif rJohn.NX_SetEVFl "Sol:NextSex", 0 rJohn.NX_SetEVFl "Sol:Busy", False endif let rJohn := Pencil01 let rJohn := GetNextRef loop let iStage := 2 DebugPrint "Sol: HOQ (%g) - Finished init" iStage return elseif iStage == 2 DebugPrint "Sol: HOQ (%g) - Start Wallace conv intro" iStage SexoutSolWallaceREF.StartConversation PlayerREF, zSolHeliosPartyStart return ; ** Finish elseif iStage == 700 DebugPrint "Sol: HOQ (%g) - Wallace start end conversation player" iStage SexoutSolWallaceREF.StartConversation PlayerREF, zSolHeliosPARTYOVER let iStage := 701 return elseif iStage == 703 let iStage := 700 return elseif iStage == 701 || iStage == 702 let iStage += 1 return elseif iStage == 9000 ; * this stage is set by wallace dialog DebugPrint "Sol: HOQ (%g) - Start stage 9000, payment" iStage foreach iter <- aGirls let rGirl := iter["value"] if eval (Call fnSexoutActorInUse rGirl) if rGirl == rBoxedBitch let iTricks += iBoxTricks let iBoxTricks := 0 let iBoxStage := 0 let rBoxedBitch := NONE endif rGirl.CIOS SexoutNGFinishNow endif loop PlayerREF.AddItem NCRMoney100, 10 RewardXP 100 AddReputation RepNVNCR, 1, 1 PlayerREF.NX_SetEVFl "SO:NotNow", False if eval iTricks > 50 && !(PlayerREF.HasPerk SexoutSolHeliosPerk) MessageBoxEx "Congratulations! Between the gang, you've screwed %g times during Helios One Festivities. You have all earned the 'Passed Around At Parties Perk'." PlayerREF.AddPerk SexoutSolHeliosPerk endif let iStage := 9001 return elseif iStage == 9002 && SexoutSolHeliosZAZBox.GetDisabled SexoutSolHeliosZAZBox.Enable ; * this delay prevents ragdoll issue from sexout anim ending let iStage += 1 elseif iStage == 9005 DebugPrint "Sol: HOQ (%g) - Sending the girls home" iStage Call tsolGoHomeBathGirls aGirls ; * Clear Idle Markers let iCount := ListGetCount SexoutSolHeliosIdleMarkersFL while iCount > 0 let iCount -= 1 let rItem := ListGetNthForm SexoutSolHeliosIdleMarkersFL, iCount rItem.Disable loop let iStage := 9006 return elseif iStage == 9120 ; * Final clear up DebugPrint "Sol: HOQ (%g) - Ending Quest" iStage foreach iter <- aGirls let rGirl := iter["value"] if rGirl != PlayerREF rGirl.RemoveScriptPackage SexoutSolNovacGoHomePKG rGirl.MoveTo SexoutSolNovacBathHouseEntrance endif rGirl.NX_SetEVFl "Sol:Busy", False loop FantasticREF.MoveTo SexoutSolFantasticHomeMarker SexoutSolHeliosZAZBox.Disable let aGirls := ar_Null let aJohns := ar_Null let aGirlIdles := ar_Null StopQuest SexoutSolHeliosOneQuest return elseif iStage > 9000 let iStage += 1 return endif ; ** The Boxed Bitch if iBoxStage == 1 ; * Start DebugPrint "Sol: HOQ (%g) - Boxed Bitch stage 1" iStage if eval !(rBoxedBitch) let rBoxedBitch := aGirls[(Rand 1, (ar_Size aGirls))] ; * skip player endif if eval !(rBoxedBitch) || (Call fnSexoutActorInUse rBoxedBitch) DebugPrint "Sol: HOQ (%g) - No boxable bitch found", iStage ; Pass elseif eval (Call fnSexoutActorInUse rBoxedBitch) || (rBoxedBitch.NX_GetEVFo "Sexout:Start::SpellTarget") DebugPrint "Sol: HOQ (%g) - Boxed bitch %n busy" iStage, rBoxedBitch ; Pass else rBoxedBitch.MoveTo SexoutSolHeliosZAZBox SexoutSolHeliosZAZBox.Disable rBoxedBitch.NX_SetEVFl "Sexout:Start::CallVer", 1 rBoxedBitch.NX_SetEVFl "Sexout:Start::nUseZAZ", True rBoxedBitch.NX_SetEVFo "Sexout:Start::ActorA", rBoxedBitch rBoxedBitch.NX_SetEVFl "Sexout:Start::Duration", 240 rBoxedBitch.NX_SetEVFl "Sexout:Start::Anim", 1021 ; * generic idle rBoxedBitch.NX_SetEVFl "Sexout:Start::IsAnal", True rBoxedBitch.NX_SetEVFl "Sexout:Start::IsVaginal", True rBoxedBitch.CIOS SexoutNGBegin rBoxedBitch.NX_SetEVFl "Sol:Busy", True let iBoxStage := 2 endif elseif iBoxStage == 2 if GetRandomPercent < 3 DebugPrint "box 2 a" let rBoxJohn := Call tsolGetLocalJohn rBoxedBitch, "Male" DebugPrint "box 2 b" if rBoxJohn != NONE DebugPrint "Sol: HOQ (%g) - %n boning the boxed bitch %n" iStage, rBoxJohn, rBoxedBitch rBoxJohn.NX_SetEVFl "Sol:Busy", True rBoxedBitch.CIOS SexoutNGFinishNow let iBoxStage := 3 endif endif elseif iBoxStage == 3 DebugPrint "box 3" if eval (Call fnSexoutActorInUse rBoxedBitch) || (rBoxedBitch.NX_GetEVFo "Sexout:Start::SpellTarget") DebugPrint "Sol: HOQ (%g) - Waiting for Boxed Bitch %n to be ready" iStage, rBoxedBitch ; Pass else DebugPrint "Sol: HOQ (%g) - Starting a boxed bitch (%n) boning by %n" iStage, rBoxJohn, rBoxedBitch rBoxedBitch.NX_SetEVFl "Sexout:Start::CallVer", 1 rBoxedBitch.NX_SetEVFl "Sexout:Start::nUseZAZ", True rBoxedBitch.NX_SetEVFo "Sexout:Start::ActorA", rBoxJohn rBoxedBitch.NX_SetEVFo "Sexout:Start::ActorB", rBoxedBitch rBoxedBitch.NX_SetEVFl "Sexout:Start::Duration", 240 rBoxedBitch.NX_SetEVFl "Sexout:Start::Anim", (NX_GetRandom 221, 227) rBoxedBitch.NX_SetEVFl "Sexout:Start::IsOral", True rBoxedBitch.CIOS SexoutNGBegin rBoxJohn.NX_SetEVFl "Sol:Busy", False let rBoxJohn := NONE let iBoxTricks += 1 let iBoxStage := NX_GetRandom 30, 60 endif elseif iBoxStage == 4 DebugPrint "Sol: HOQ (%g) - Ending boxed bitch boning" iStage rBoxedBitch.CIOS SexoutNGFinishNow rBoxJohn.NX_SetEVFl "Sol:Busy", False if GetRandomPercent < ((iBoxTricks - 2) * 30) let iBoxStage := -999 else let iBoxStage := 1 endif elseif iBoxStage > 4 let iBoxStage -= 1 elseif iBoxStage == -999 ; * End DebugPrint "Sol: HOQ (%g) - Time in the box is over for %n" iStage, rBoxedBitch rBoxedBitch.NX_SetEVFl "Sol:Busy", False SexoutSolHeliosZAZBox.Enable let iTricks += iBoxTricks let iBoxTricks := 0 let iBoxStage := 0 SexoutSolWallaceREF.StartConversation rBoxedBitch, zSolHeliosBoxBitchEND let rBoxedBitch := NONE endif ; *** General Scanner if eval (iStage % 10 == 0) foreach iter <- aGirls let rGirl := iter["value"] if eval (Call fnSexoutActorInUse rGirl) || (rGirl.NX_GetEVFo "Sexout:Start::SpellTarget") continue elseif eval (rGirl.NX_GetEVFl "Sol:Busy") DebugPrint "Sol: HOQ (%g) - %n is sol-busy, but not sexout in use" iStage, rGirl continue elseif rGirl == SexoutSolGerdaREF DebugPrint "Sol: HOQ (%g) - Gerda tap dance" iStage rGirl.PlayIdle "SpecialIdleNVTapDance" if GetRandomPercent < 75 ; * poor gerda continue endif elseif rGirl == PlayerREF ; Pass else DebugPrint "Sol: HOQ (%g) - %n playidle" iStage, rGirl rGirl.PlayIdle aGirlIdles[(Rand 0, (ar_Size aGirlIdles))] endif foreach nestiter <- aJohns let rJohn := nestiter["value"] if eval (Call fnSexoutActorInUse rJohn) || (rJohn.NX_GetEVFo "Sexout:Start::SpellTarget") continue elseif eval (rJohn.NX_GetEVFl "Sol:NextSex") > iStage || (rJohn.NX_GetEVFl "Sol:Busy") continue elseif rJohn == CraigBooneREF && rGirl != SexoutSolGerdaREF continue else DebugPrint "Sol: HOQ (%g) - %n start conv %n for general debauchery" iStage, rJohn, rGirl rJohn.StartConversation rGirl, zSolHeliosJohnSTART if eval (rJohn.GetDistance rGirl) < 1000 break endif endif loop let aJohns := Call tsolShuffle aJohns loop if iStage == 500 ; * Fantastic figures out no one invited him to the party if eval (ar_Find FantasticREF, aJohns) == ar_BadNumericIndex ar_Append aJohns, FantasticREF FantasticREF.MoveTo SexoutSolHeliosOneExteriorExitMarker FantasticREF.AddScriptPackage SexoutSolHeliosOnePKG FantasticREF.evp endif endif if eval (iStage % 100) == 0 && iBoxStage == 0 && GetRandomPercent < 40 let iBoxStage := 1 endif DebugPrint "Sol: HOQ (%g) - Completed general scan" iStage endif ; * Timer if iStage >= 100 && iStage < 700 let iStage += 1 endif ; *** Do tricks if rTrickGirl != NONE DebugPrint "start trick" let IsValid := False if eval (Call fnSexoutActorInUse rTrickGirl) DebugPrint "Sol: HOQ (&g) - rTrickGirl %n is sexout in use", iStage, rTrickGirl elseif eval (rTrickGirl.NX_GetEVFl "Sol:Busy") DebugPrint "Sol: HOQ (%g) - rTrickGirl %n is sol-busy but not sexout in use", iStage, rTrickGirl elseif eval (rTrickGirl == SexoutSolGerdaREF) && (rTrickJohn == NONE) DebugPrint "Sol: HOQ (%g) - Error! attempted to start a solo fuck for Gerda", iStage else let IsValid := True endif if IsValid != True let rTrickGirl := NONE let rTrickJohn := NONE let sex_type := "Any" let SubTrick := False return endif DebugPrint "Sol: HOQ (%g) - STARTING TRICK for %n + %n, sub: %g, type: %z", iStage, rTrickGirl, rTrickJohn, SubTrick, sex_type rTrickGirl.NX_SetEVFl "Sexout:Start::CallVer", 1 let rItem := NONE if rTrickGirl == SexoutSolGerdaREF let sex_type := "Oral" let SubTrick := False elseif eval (sex_type != "Any") && !(ar_HasKey sol.aSexType, sex_type) PrintC "Sol: HOQ - Error! trick called for " + $rTrickGirl + " with undefined sex_type: " + sex_type + " (Fixing)" let sex_type := "Any" elseif eval (sex_type == "Any") let aTemp := ar_List "Anal", "Oral", "Vaginal", "DoubleTimed", "Masturbate", "Grind" let sex_type := aTemp[(Rand 0, (ar_Size aTemp))] if GetRandomPercent < 15 let SubTrick := True endif DebugPrint "Sol: HOQ (%g) - Trick type was unset, picking %z with sub: %g" iStage, sex_type, SubTrick endif DebugPrint " Trick 1" if rTrickJohn != NONE DebugPrint "Trick 1.1" if eval ( eval (rTrickJohn.GetIsSex "Female") && (eval (sex_type == "Vaginal") || eval (sex_type == "Anal")) ) || eval (sex_type == "Peg") DebugPrint "Trick 1.2" let rItem := ListGetNthForm SexoutSolStraponsFL, (Rand 0, (ListGetCount SexoutSolStraponsFL)) DebugPrint "Trick 1.3" endif elseif eval sex_type != "Masturbate" DebugPrint "Sol: HOQ (%g) - sex_type '%z' is invalid because no john was set, fixing by masturbating", sex_type let sex_type := "Masturbate" endif DebugPrint "Trick 2" if eval sex_type == "Masturbate" rTrickGirl.NX_SetEVFo "Sexout:Start::ActorA", rTrickGirl rTrickGirl.NX_ClrEVFo "Sexout:Start::ActorB" elseif SubTrick rTrickGirl.NX_SetEVFo "Sexout:Start::ActorA", rTrickGirl rTrickGirl.NX_SetEVFo "Sexout:Start::ActorB", rTrickJohn if rItem != NONE rTrickGirl.AddItem rItem, 1 rTrickGirl.EquipItem rItem endif else rTrickGirl.NX_SetEVFo "Sexout:Start::ActorA", rTrickJohn rTrickGirl.NX_SetEVFo "Sexout:Start::ActorB", rTrickGirl if rItem != NONE rTrickJohn.AddItem rItem, 1 rTrickJohn.EquipItem rItem endif ; ** remove buttplugs if eval sex_type == "Anal" || sex_type == "DoubleTimed" let rItem := rTrickGirl.GetEquippedObject mn["buttplug"] if rItem != NONE DebugPrint "Sol: HOQ (%g) - Removing buttplug for %n", iStage, rTrickGirl rTrickGirl.UnequipItem rItem if rTrickGirl != PlayerREF rTrickGirl.RemoveItem rItem, 1 endif endif endif endif DebugPrint "Trick 3" if eval sex_type == "Oral" ; ** remove gags let rItem := rTrickGirl.GetEquippedObject mn["Gag"] if rItem != NONE rTrickGirl.UnequipItem rItem if rTrickGirl != PlayerREF rTrickGirl.RemoveItem rItem, 1 endif endif rTrickGirl.NX_SetEVFl "Sexout:Start::IsOral", True rTrickGirl.NX_SetEVFl "Sexout:Start::bDontUndressB", True elseif eval sex_type == "Grind" rTrickGirl.NX_SetEVFl "Sexout:Start::IsVaginal", True rTrickGirl.NX_SetEVFl "Sexout:Start::Anim", sol.aGrindAnims[(Rand 0, (ar_Size(sol.aGrindAnims)))] rTrickGirl.NX_SetEVFl "Sexout:Start::bDontUndressA", True rTrickGirl.NX_SetEVFl "Sexout:Start::bDontUndressB", True elseif eval sex_type == "DoubleTimed" rTrickJohn.NX_SetEVFl "Sol:Busy", True let rJohn := Call tsolGetLocalJohn, rTrickGirl, "Male" rTrickJohn.NX_SetEVFl "Sol:Busy", False if rJohn != NONE rTrickGirl.NX_SetEVFo "Sexout:Start::ActorC", rJohn rTrickGirl.NX_SetEVFl "Sexout:Start::IsVaginal", True rTrickGirl.NX_SetEVFl "Sexout:Start::IsAnal", True endif elseif eval sex_type == "Vaginal" rTrickGirl.NX_SetEVFl "Sexout:Start::IsVaginal", True elseif eval sex_type == "Anal" || sex_type == "Peg" rTrickGirl.NX_SetEVFl "Sexout:Start::IsAnal", True endif DebugPrint "Trick 4" if eval sex_type == "Masturbate" let iDuration := Rand 10, 15 else let iDuration := Rand (Sexout.dfTime / 2), (Sexout.dfTime * 1.5) endif rTrickGirl.NX_SetEVFl "Sexout:Start::Duration", iDuration rTrickGirl.CIOS SexoutNGBegin rTrickJohn.NX_SetEVFl "Sol:NextSex", (iStage + iDuration + 30) let rTrickGirl := NONE let rTrickJohn := NONE let sex_type := "Any" let SubTrick := False let iTricks += 1 DebugPrint "Sol: HOQ (%g) - Completed a trick setup for %n + %n : %z %g" iStage, rTrickGirl, rTrickJohn, sex_type, SubTrick endif DebugPrint "Sol: HOQ - completed a run, istage is currently %g" iStage End
prideslayer Posted May 28, 2014 Posted May 28, 2014 As may have been implied from previous posts, I've been battering NVSE 4 with compiler override to see when it caves. A little additional insight: This line: if eval ( ((rTrickJohn.GetIsSex "Female") && (sex_type == "Vaginal" || sex_type == "Anal")) || (sex_type == "Peg") ) Causes my script to eat itself and never run again, every time (~15) I've tested it. I don't think it's too complicated, I think it's just not explicit enough. You're not checking the actual result of that first function call. Try this? if eval (((1 == (rTrickJohn.GetIsSex "Female")) && (sex_type == "Vaginal" || sex_type == "Anal")) || (sex_type == "Peg")) I also stuffed one additional set of parens in there You shoudl also flip the constant side of all of those around as well, see my first or second post in this thread. '"Vaginal" == sex_type' is preferable to 'sex_type == "Vaginal"'.
Odessa Posted May 28, 2014 Posted May 28, 2014 Try this? if eval (((1 == (rTrickJohn.GetIsSex "Female")) && (sex_type == "Vaginal" || sex_type == "Anal")) || (sex_type == "Peg")) I also stuffed one additional set of parens in there No difference. As mentioned, splitting the line makes it work, so I think the problem is its too busy. Also, it eats the script, not misevaluates. You shoudl also flip the constant side of all of those around as well, see my first or second post in this thread. '"Vaginal" == sex_type' is preferable to 'sex_type == "Vaginal"'. Disagree, my personal opinion is that flipping makes it harder to read and serves no other purpose. The compiler spots errors like 'sex_type := "Vaginal"'. Probably we come back from different programming language backgrounds.
nyaalich Posted May 28, 2014 Posted May 28, 2014 You shouldn't have quotation marks around female for the getissex check.
Odessa Posted May 28, 2014 Posted May 28, 2014 Actually, "Female" is a string in the vanilla game, like PlayIdle "idles" and many other function arguments. If you remove the quotes then the CO precompiler will simply add them back in, and show a warning.
prideslayer Posted May 28, 2014 Posted May 28, 2014 There's no way in hell that the expression is too busy/complicated, something else is going on. Maybe the ref is bad. Calling a ref method (rather than using a ref as a param) will kill a script the way you describe if the ref is invalid. This works fine as a script on a test quest with a 3s delay in an otherwise empty ESP. scn testQuestScript int init int rnd string_var s Begin GameMode let rnd := NX_GetRandom 1 3 if (1 == rnd) let s := "foo" elseif (2 == rnd) let s := "bar" else let s := "baz" endif if eval (((player.GetIsSex "Female") && ("foo" == s || "bar" == s)) || ("baz" == s)) printc "true" else printc "false %z" s endif sv_destruct s End
DoctaSax Posted May 28, 2014 Posted May 28, 2014 I'm... slightly intimidated by Odessa's spoilered script there I see you using ref != NONE and ListGetFormIndex != NOTFOUND, NX_SetEVFL'ing booleans to true... all this checks out? could it be that if rTrickJohn != NONE just doesn't work the way you think it would? Perhaps you clicked away the PU warning about unquoted strings, and it compiled thinking NONE == "NONE", so you might've indeed ended up with an invalid ref? Another avenue here that can explain the difference is the script line size limit - strings taking at least a byte per character - but I've definitely used more than that in scripts before. Perhaps the combination of CO, eval, logical operators and strings just makes the line's compiled size grow somehow, but that's pure conjecture. These are the things that modder's superstition is built on. Lastly pride does use the flipping method, and although I'm not a fan of it in regular scripts, it can help with all this stuff. I also would've added even more parentheses: ((sex_type == "Vaginal") || (sex_type == "Anal"))
Guest Posted May 28, 2014 Posted May 28, 2014 Another avenue here that can explain the difference is the script line size limit - strings taking at least a byte per character - but I've definitely used more than that in scripts before. Perhaps the combination of CO, eval, logical operators and strings just makes the line's compiled size grow somehow, but that's pure conjecture. can't say anything about if eval, CO or string_vars, but in the last script I placed logical operators checking a lot of functions all in a row and it worked fine, I'm speaking about 4-5 times Odessa's lenght: can't really say that a line itself has a limit of few characters by the way, instead of checking if ref is null, why dont check if ref is not null?
Halstrom Posted May 28, 2014 Author Posted May 28, 2014 can't say anything about if eval, CO or string_vars, but in the last script I placed logical operators checking a lot of functions all in a row and it worked fine, I'm speaking about 4-5 times Odessa's lenght: can't really say that a line itself has a limit of few characters by the way, instead of checking if ref is null, why dont check if ref is not null? Yeah I didn't think there was a reliable way of checking if a ref was null so I've always done this: If rActor ; // *** Actor is Valid else ; // *** Actor is Null endif
Odessa Posted May 29, 2014 Posted May 29, 2014 @Prideslayer: My debug prints rTrickJohn as 'NCR Trooper' or another valid NPC, and the sex_type as an expected string. I catch empty references earlier. I have debug on the line directly above (always prints) and below (never). --- @DoctaSax I have tried many combinations of gratuitous brackets on that line. It all compiles with no warnings- I've defined 4 global variables in the GECK: True = 1, False = 0, NONE = 0, NOTFOUND = -1. The entire script completes as expected without that line (note the fuck load of debug print to check, cos I was skeptical too). I personally feel it is easier to manage code like this: 'if rActor == 0' or 'let rActor := 0' is misleading because references aren't numbers (in terms of sane coding), and using 'NONE' for refs instead separates them. 'if rActor' alone is vague. Using True and False is much easier to read and makes the purpose of a variable obvious. 0 or 1 isn't really a number, its a flag, this way numeric scalars are clearly distinct. Now we can do array maps, I have also defined every vanilla magic number in my main quest, hence instead of crap like this: 'Player.GetEquippedObject 10' or 'if rItem.GetObjectType == 40' I can just pass a reference to the map as 'mn' and: 'Player.GetEquippedObject mn["Hat"]' or 'if rItem.GetObjectType == mn["Weapon"]. Hence, I have removed all numbers in my code that refer to empty refs, constants or flags, they solely refer to 'real' scalars. You need CO for the magic number map, but I think anyone who hasn't started using the CO by default has only realized half the benefit of NVSE4.
Guest Posted May 29, 2014 Posted May 29, 2014 anyone who hasn't started using the CO by default has only realized half the benefit of NVSE4. I guess I still have to realize that. All I know is CO wasn't compiling too many lines of my script when the GECK compiler was working. It would have required me to understand its taste concerning "how" to re-write the whole script, which I find quite... weird
DoctaSax Posted May 29, 2014 Posted May 29, 2014 can't say anything about if eval, CO or string_vars, but in the last script I placed logical operators checking a lot of functions all in a row and it worked fine, I'm speaking about 4-5 times Odessa's lenght: can't really say that a line itself has a limit of few characters I'm not talking in-script size, but compiled size. EditorIDs and functions that have a long name may still compile to a small size, like a few bytes. Strings, on the other hand use at least one byte per character in them. While pulling together some intel on eval's tricksiness, I saw a similar problem in one of the obse threads, where max line size was said to be the culprit in this line crashing Oblivion's CS: if eval ((confArray[5]["combinations"][0]["req"]) == 1 || (confArray[5]["combinations"][2]["req"]) == 1 || (confArray[5]["combinations"][3]["req"]) == 1) In separate lines, all was fine. And well, it's similar enough for me to remember it. Max size was said to be at 73 bytes, and that is for 'set' and 'if', not 'let'. So it's a vanilla limitation, you just come across it more easily with the new stuff. But I have no idea how much of this, if anything, applies to FNV. Also, the problem was raised in the context of the CS crashing when trying to compile, not in-game. On the other hand, if people couldn't get it to compile, testing in-game was impossible, so who knows, eh. (Some of all this is still a bit a mystifying, so I tend to go with better safe and sorry, or the evil thing from down below will call down bad juju from up on high and we'll have seven years of log-less bug reports.) I've defined 4 global variables in the GECK: True = 1, False = 0, NONE = 0, NOTFOUND = -1. The entire script completes as expected without that line (note the fuck load of debug print to check, cos I was skeptical too). Oh, I see. Now we can do array maps, I have also defined every vanilla magic number in my main quest, hence instead of crap like this: 'Player.GetEquippedObject 10' or 'if rItem.GetObjectType == 40' I can just pass a reference to the map as 'mn' and: 'Player.GetEquippedObject mn["Hat"]' or 'if rItem.GetObjectType == mn["Weapon"]. Hence, I have removed all numbers in my code that refer to empty refs, constants or flags, they solely refer to 'real' scalars. You need CO for the magic number map, but I think anyone who hasn't started using the CO by default has only realized half the benefit of NVSE4. I have to disagree there... obviously that's an example I would use CO with, but the CO makes me doubt things I used to take for granted too much to use by default. Needing more parentheses than I'd have thought, parameter strings needing quoting, stuff like that. I'll use it if I see a need or benefit, otherwise I'm fine without.
Odessa Posted May 29, 2014 Posted May 29, 2014 I will concede that the CO is less exciting during in-game debugging than in my text editor Players might not appreciate the thrill I got from doing something in 1-line that would otherwise take ~10 on the occasions it flops...
Guest Posted May 29, 2014 Posted May 29, 2014 Also, the problem was raised in the context of the CS crashing when trying to compile, not in-game. I think if you reach the script limit (for the lenght, don't know anything about the 73 bytes) in NV you don't crash, you compile, with errors too, just to see the script breaking in game. So this could be the case.
jaam Posted May 29, 2014 Posted May 29, 2014 Hey guys it is a script language not C++ I know its easy to get carried away (I do too) but splitting in multiple line is better for some reasons. 1) the language does not shortcut the evals. It will calculate everything even if it already knows the final value. 2) when PrintC debugging, checking every comparison individually pinpoint the issue faster. and 3) multiple lines are easier to read, specially month later. Also remember that operator precedence is not natural: OR has a higher priority than AND. As for the older of member in comparison, it only matters with language using = for assignment. And anyway, this script language will not confuse a comparison and an assignation.
jaam Posted May 29, 2014 Posted May 29, 2014 The maximum length of a line during compilation in vanilla was 255 or 256, with OBSE or NVSE 3 it should be 32767 something. 32767 should also be the maximum size of the script in the RichEdit dialog. This one limit you cannot miss. I never tried to determine the maximum size of the script once complied, or the maximum size of a compiled individual line. But if it is also at least 32767, it should not be possible to reach it with a 32767 script source. During execution, the script buffer is allocated dynamically so there is not a preset limit. One cannot rule out a memory allocation error, but I would think NVSE would loudly catch it.
prideslayer Posted May 29, 2014 Posted May 29, 2014 Hey guys it is a script language not C++ I know its easy to get carried away (I do too) but splitting in multiple line is better for some reasons. 1) the language does not shortcut the evals. It will calculate everything even if it already knows the final value. This is true, and a quick way to shoot yourself in the foot with a script. Lines like this: if (1 == IsReference rFoo) && (1 == rFoo.IsScripted) Do not work as expected. Even if the first check is false, the second one is still run (no boolean short-circuit, as you said) and will crash the script.
prideslayer Posted May 29, 2014 Posted May 29, 2014 Also, I'm pretty sure the maximum size of a compiled script is 16K.
nyaalich Posted May 29, 2014 Posted May 29, 2014 Updated FNVEdit. From Change Log: Version 3.0.32 contains the following changes:- issue 69: automatic updating of counter fields to reflect the proper amount of elements in containers- issue 149: FormID indexes in master file header ONAM forms- issue 162: reference rotation angle normalization (TES4LODGen hanging on several mods)- hotkeys in plugins selection window (Enter - confirm, numpad '+' select all, '-' select none, '*' invert)- hold Shift while starting xEdit to skip restoring window state (for users stuck with xEdit outside of viewable desktop area)- hold Shift while clicking OK in plugins selection window for one time skipping of building references for all plugins- exclude building references for plugins list available in options- option to display integer values of flags and enumerations (off by default)- Ctrl+C copies only Node text to clipboard, Esc closes the View window- definitions update for all games to reduce false positives when checking for errors- custom scripted filtering, demo 'Apply custom scripted filter.pas'- new scripting functions and scripts: Weather Editor script (Ctrl+W), Worldspace Browser (Alt+F3)- scripted persistent bookmarking of records: Ctrl+1..5 to set a bookmark, Alt+1..5 to go back- removing offset data in WRLD is optional now, 'on' by default- [TES5] TES5LODGen (beta version, has several issues)- [TES5] renamed armor addon nodes (added slot numbers), please update your scripts if needed- [TES5] Record definitions update (WTHR, DOBJ, NAVM, VMAD papyrus data, GetEventData condition), improved NavMeshes (thanks to jonwd7)- [TES5] Added VMAD (papyrus scripts) to TREE, and LVLG (global) to LVLN. They can't be edited in CK, but it supports them and they confirmed to work in game- [TES4] Added XRGD subrecord to REFR, INFO flags update- [FO3] Do not remove PLD2 subrecord in PACK (as in FNV)- [FNV] BPTD update to support body parts without BPTN name- [FNV] Relocated CELL and WRLD groups at the end of file- [TES4/TES5/FO3/FNV] WRLD offset data OFST definition (when 'Simple records' option is off)
nyaalich Posted May 29, 2014 Posted May 29, 2014 Showing Mod's Version in FOMM's Package Manager: Is there a way to do this with just an esp as opposed to creating a zip w/ a FOMM xml file?
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now