Jump to content

Fallout New Vegas GECK & Scripting Help 101


Recommended Posts

Guest tomm434
Posted

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.

Posted

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.

Posted
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?

Posted

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

 

 

 

Posted

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"'.

Posted

 

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.

Posted

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.

Posted

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
Posted

I'm... slightly intimidated by Odessa's spoilered script there :blush:

 

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"))

Posted

 

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?

Posted

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

Posted

@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.

 

 

Posted

 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 :o

Posted

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.

Posted

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...

Posted

 

 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.

Posted

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.

 

 

Posted

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.

 

Posted

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.
Posted

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)

 

 

Posted

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?

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...