Jump to content

PAF Fixes and Addons


Recommended Posts

Posted (edited)
7 hours ago, Dg75 said:

Kool ! 

I have the DynamicPoop function updated so it wont conflict, I just need to do the same to the AnalSpray Function as both use idle conditions to set values. 

I'll have an update up soon.

 

I noticed in your jason you only have gsposes 23/06 and that only two of the 20/03 originals are added.

EndUser can always add them if wanted. Or maybe add them by default.. I suppose the purpose was to replace the 20/03

so I understand if you prefer not to. Either or - its primary reason it best to leave as optional patch. 

Neat sounds good.

I just used poserhotkeys and looked through all poses in the 23/06 poser and put in those that seemed like they may be usable or interesting in some way to make the json. It did feel like some poses I had seen in the old poser have been missing, but since the "gs123" pose numbers seem to have changed between 20/03 and 23/06 and they dont have names... its hard to know unless you can tell them apart visually. The json does have most old poses that I found in the new poser its just that the numbers changed gs11 is not gs11 in the newer etc.
There isnt a changelog on the patreon so its difficult to tell if some poses have been removed from the poser or just re-ordered.
21/07 is now the newest btw

Good thing about the approach with the json is you can ship it with a selection of your choice and people can change it to whatever poser/animations they use without editing the scripts.
So yeah in my selection for now I only have gsposes from 23/06 as that still gets updated, but nothing wrong with just using the old one either. Personally I probably will mix and throw in some poses from other pose mods into the many empty placeholder slots gunslicer has as well so I dont need to have multiple pose mods installed.
Looking at your old script this should be the selection for the 20/03 poser.

{
  "extra_idles_f": [
    { "event": "GS11",  "label": "GS11 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS12",  "label": "GS12 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS485", "label": "GS485 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS532", "label": "GS532 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS505", "label": "GS505 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS510", "label": "GS510 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS304", "label": "GS304 (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS497", "label": "GS497 (non-DP)", "enabled": true, "dpExempt": true },

    { "event": "GS148", "label": "GS148 (Poop)", "enabled": true, "dpExempt": false },
    { "event": "GS292", "label": "GS292 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS320", "label": "GS320 (Poop)", "enabled": true, "dpExempt": false },
    { "event": "GS365", "label": "GS365 (Poop)", "enabled": true, "dpExempt": false },
    { "event": "GS366", "label": "GS366 (Poop)", "enabled": true, "dpExempt": false },
    { "event": "GS404", "label": "GS404 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS406", "label": "GS406 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS458", "label": "GS458 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS503", "label": "GS503 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS509", "label": "GS509 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS514", "label": "GS514 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS501", "label": "GS501 (Both)", "enabled": true, "dpExempt": false },
    { "event": "GS542", "label": "GS542 (Both)", "enabled": true, "dpExempt": false }
  ],

  "extra_idles_m": [
    { "event": "GS198", "label": "Example Male Pose - Replace Me", "enabled": false, "dpExempt": false }
  ]
}

Trying to give the poses names with just a few words
 

Spoiler
{
  "extra_idles_f": [
    { "event": "GS11",  "label": "GS11 Half Squat Hip Shake (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS12",  "label": "GS12 Half Squat Hip Shake (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS485", "label": "GS485 Cat Stretch (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS532", "label": "GS532 Pet leg lift look back (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS505", "label": "GS505 On Back Pelvis Lifting (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS510", "label": "GS510 Bend Over Hip Sway (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS304", "label": "GS304 Bend Over Legs closed (non-DP)", "enabled": true, "dpExempt": true },
    { "event": "GS497", "label": "GS497 Kneel Look Back (non-DP)", "enabled": true, "dpExempt": true },

    { "event": "GS148", "label": "GS148 Slav Squat", "enabled": true, "dpExempt": false },
    { "event": "GS292", "label": "GS292 Lean Back Spread Jerking Masturbating", "enabled": true, "dpExempt": false },
    { "event": "GS320", "label": "GS320 Kneel Look Back", "enabled": true, "dpExempt": false },
    { "event": "GS365", "label": "GS365 Sit Sideways Legs closed", "enabled": true, "dpExempt": false },
    { "event": "GS366", "label": "GS366 Sit Sideways Legs spread", "enabled": true, "dpExempt": false },
    { "event": "GS404", "label": "GS404 All Fours Back Stretch", "enabled": true, "dpExempt": false },
    { "event": "GS406", "label": "GS406 Kneeling Book", "enabled": true, "dpExempt": false },
    { "event": "GS458", "label": "GS458 Casual Squat Modest", "enabled": true, "dpExempt": false },
    { "event": "GS503", "label": "GS503 Kneel Legs spread", "enabled": true, "dpExempt": false },
    { "event": "GS509", "label": "GS509 Bend Over Legs Closed", "enabled": true, "dpExempt": false },
    { "event": "GS514", "label": "GS514 Sit Lean Back Spread", "enabled": true, "dpExempt": false },
    { "event": "GS501", "label": "GS501 Cowgirl", "enabled": true, "dpExempt": false },
    { "event": "GS542", "label": "GS542 Sit Lean Back Spread Wider", "enabled": true, "dpExempt": false }
  ],

  "extra_idles_m": [
    { "event": "GS198", "label": "Example Male Pose - Replace Me", "enabled": false, "dpExempt": false }
  ]
}

 

 

Edited by Alpia
Posted

Sorry to bother you, but I can't get my character to play a pee animation. She seems to be in the "playing" animation state, but her body is still stuck in the normal standing idle animation. Could you please provide some assistance? I'm sure I have ZAZ animations8+ installed. By the way, English isn't my native language, and I apologize for any possible vocabulary and grammatical errors. I used Google Translate:)image.png.2e03eb60c47e3c714e759aff6ce30354.pngimage.png.42bf438e5f82369d820a4f91f7194902.pngimage.png.9204fc60a70287b841baf809bb7cafda.png

Posted (edited)
10 hours ago, stalin233111 said:

I can't get my character to play a pee animation.

Have you run your animation patcher ? e.g fnis or nemeses or pandora or whatever is used now a days..

I know its a silly question but its always the first thing to pop in mind. Your mcm pics seem okay. 

 

Past that - make sure no other random idles are conflicting like arousal's shame idle

if another idle calls roughly same time as paf's idle does they conflict and neither would work.

If another idle trys to play and if its a replacer(open animation replacer) then it wouldn't matter

as fnis type patchers always win conflicts over replacers.(so i've been told)

Edited by Dg75
Posted (edited)
21 hours ago, Alpia said:

but since the "gs123" pose numbers seem to have changed between 20/03 and 23/06

So its possible some with different names may actually be the same pose(or close match) as the old ones.

Best leave the jason as you have it then, I'll work through the new poses and if they match old pose I can just 

add the new name in to pass the conditions for those offsets.. later update, primary concern now is to get 4.7.2 up hopefully this weekend.

Edited by Dg75
Posted
3 hours ago, Dg75 said:

So its possible some with different names may actually be the same pose(or close match) as the old ones.

Best leave the jason as you have it then, I'll work through the new poses and if they match old pose I can just 

add the new name in to pass the conditions for those offsets.. later update, primary concern now is to get 4.7.2 up hopefully this weekend.

Yes mostly same poses different names best to just take a look at the poses in game. Did mark a few more poses with (-dp) those with that mark dont seem suitable for the dynamic pooping. The GS 21/07 didnt change numbers from GS 23/06 so still fits PAF_ExtraIdles.json

For my own use I added a small extra function "Preview all poses" toggle with a hotkey that one can bind. Turn the toggle on, and your character will strike the first pose from the pose list along with an on-screen label showing its name and if enabled and dpexcempt. Press the key to move to the next one, and so on through the whole list.
More a debug/testing thing, so not for your release, but maybe interesting for you to when trying to preview poses. Makes it easier to check out all poses as you dont have to reopen the mcm constantly to take a look at the next pose.
I add it in the spoiler if you want it for your own testing. 

Spoiler

PAF_MainQuestScript.psc  
PFA_PAFMCM.psc

PFA_PAFMCM.psc:

Bool PreviewActive
Bool PreviewIsMale
Int PreviewIndex = -1
Int PreviewStyle = -1
Int PreviewKey = -1

For MCM Ui

AddToggleOptionST("OID_PreviewIdles", "$PFAPreviewIdles_", PreviewActive)
AddKeyMapOptionST("OID_PreviewKey", "$PFAPreviewKey_", PreviewKey)

States for the options

State OID_PreviewIdles
    Event OnHighlightST()
        SetInfoText("$PFAPreviewIdlesInfo_")
    EndEvent
    Event OnSelectST()
        if  PreviewActive
            StopIdlePreview()
        else
            StartIdlePreview()
        endif
        SetToggleOptionValueST(PreviewActive)
    EndEvent
    Event OnDefaultST()
        StopIdlePreview(True)
        SetToggleOptionValueST(False)
    EndEvent
EndState

Keybind widget like your oid_dootykey

State OID_PreviewKey
    Event OnHighlightST()
        SetInfoText("$PFAPreviewKeyInfo_")
    EndEvent
    Event OnKeyMapChangeST(int newKeyCode, string conflictControl, string conflictName)
        if newKeyCode == 1 || !ResolveConflict(newKeyCode, conflictControl, conflictName)
            if  newKeyCode == 1
                newKeyCode = -1
            endif
            UnregisterForKey(PreviewKey)
            PreviewKey = newKeyCode
            if  PreviewKey > 0
                RegisterForKey(PreviewKey)
            endif
            SetKeyMapOptionValueST(PreviewKey)
        endif
    EndEvent
    Event OnDefaultST()
        UnregisterForKey(PreviewKey)
        PreviewKey = -1
        SetKeyMapOptionValueST(PreviewKey)
    EndEvent
EndState

Needed three new functions

Function StartIdlePreview()
    if  PreviewActive || PAF_MainQuest.GetIsAnimating()
        Return
    endif
    Int nF = GetExtraIdleCount(False)
    Int nM = GetExtraIdleCount(True)
    if  nF <= 0 && nM <= 0
        ShowMessage("$PFAListEmpty_", False)
        Return
    endif
    if  PreviewKey <= 0
        ShowMessage("$PFAPreviewNoKey_", False)
        Return
    endif
    PreviewActive = True
    PreviewIsMale = (nF <= 0)
    PreviewIndex = -1
    PreviewStyle = -1
    Debug.Notification("$PFAPreviewStarting_")
    AdvancePreview()
EndFunction

Function StopIdlePreview(Bool silent = False)
    if  !PreviewActive
        Return
    endif
    PreviewActive = False
    if  PreviewStyle >= 0
        PAF_MainQuest.PlayPeeIdleStop(PlayerRef, PreviewStyle, !PreviewIsMale)
        PreviewStyle = -1
    endif
    if  !silent
        Debug.Notification("$PFAPreviewStopped_")
    endif
EndFunction

Function AdvancePreview()
    if  !PreviewActive
        Return
    endif
    PreviewIndex += 1
    Int count = GetExtraIdleCount(PreviewIsMale)
    if  PreviewIndex >= count
        if  !PreviewIsMale && GetExtraIdleCount(True) > 0
            PreviewIsMale = True
            PreviewIndex = -1
            AdvancePreview()
            Return
        else
            StopIdlePreview(True)
            Debug.Notification("$PFAPreviewComplete_")
            Return
        endif
    endif
    Int base = 13
    if  PreviewIsMale
        base = 12
    endif
    Int style = base + PreviewIndex
    String ev = GetExtraIdleEvent(PreviewIndex, PreviewIsMale)
    String lbl = GetExtraIdleLabel(PreviewIndex, PreviewIsMale)
    String genderTxt = "F"
    if  PreviewIsMale
        genderTxt = "M"
    endif
    Debug.Notification("[" + genderTxt + " " + (PreviewIndex + 1) + "/" + count + "] " + lbl + "  (" + ev + ")")
    PreviewStyle = style
    PAF_MainQuest.PlayPeeIdleStart(PlayerRef, style, !PreviewIsMale)
EndFunction

OnKeyDown before the existing dootykey logic

Event OnKeyDown(Int KeyCode)
    if  KeyCode == PreviewKey && PreviewKey > 0
        if  PreviewActive
            UnregisterForKey(PreviewKey)
            AdvancePreview()
            if  PreviewKey > 0
                RegisterForKey(PreviewKey)
            endif
        endif
        Return
    endif
    if  KeyCode != DootyKey || ...   ; unchanged, existing DootyKey handling continues below

PAF_MainQuestScript.psc in beginidle event small utility wait

Int Function BeginIdleEvent (Actor a_actor, Int style, Bool forFem = True)
    Create_Idles()
    String IdleEventName
    a_actor.PlayIdle(PAF_IdleReset)
    Utility.Wait(0.3)
    ActorUtil.ClearPackageOverride(a_actor)
    if  forFem
        IdleEventName = PafIdlesF[style]
    else
        IdleEventName = PafIdlesM[style]
    endif
    Debug.SendAnimationEvent(a_actor, IdleEventName)
EndFunction

Translation keys added
$PFAPreviewIdles_, $PFAPreviewIdlesInfo_, $PFAPreviewKey_, $PFAPreviewKeyInfo_, $PFAPreviewNoKey_, $PFAPreviewStarting_, $PFAPreviewStopped_, $PFAPreviewComplete_

 

Posted (edited)
21 hours ago, Alpia said:

"Preview all poses"

Kool! I'll take a look at it. 

 

Yeah it'l take me a bit to flip through the idles, I have a test jig to set dp values or mark as exempt, but its one idle at a time

a little time consuming.

 

As for now I have functions completed just have to test it out. 

Best I could come up with was to set up string arrays that represent types of offset conditions. 

they are designed to function with or without the patch, it just makes 

DP functions compatible with the pose names being altered.

I'll test what I have and if all goes well post a 4.7.2 update with it and go from there.

I have in PafMainScript edited functions: DynamicPoop, AnalSpray, and I think I edited CheckWorn a while back 

nothing else should have been altered from the 4.7.1 last update - I'll double check to make sure.

Edited by Dg75
Posted (edited)
On 7/21/2026 at 8:43 PM, Alpia said:

If you are about to post a update I'll wait till I look into it more.

4.7.2 is up. The only changes in PafMainScript are the DynamicPoop and AnalSpray functions, and I added new functions directly under 

the Create_Idles function inside the Utilities section.  Above post I mentioned that I may have edited CheckWorn - I did not ! 

I did edit a value in PushPno : ModEvent.PushInt(iModEventHandle, 60) ; the 60 was an 180(optional, not even certain it does anything)

this value is a timeout sent pno if pno handles things.

Mcm has not been edited. 

 

Spoiler

new

 

String[] StyleAdjustment
String[] StyleNonAdjustment
String[] StyleAdjustmentAp

 

; DP Functions now call on RetrievePafIdleEvent to retrieve chosen pose event name to compare with below lists in 

; order to parse conditions for offset or default values.

 

String Function RetrievePafIdleEvent(Int n, Bool IsMale = False)   ; new, created for pfa 4.7.2 primarily to receive an idle name for chosen idles to play.
    int r
    if  !IsMale
        r = PafIdlesF.Length
    else
        r = PafIdlesM.Length
    endif
    if  n < 0 || r <= 0 || n > r
        Return -1   ; oops Should of been return "", somehow it compiled.. maybe the compiler took it as "" . just seen this
    endif
    if  !IsMale
        Return PafIdlesF[n]
    endif
    Return PafIdlesM[n]
EndFunction

;\

the below three functions idle names are from the original 20/03 gs poses

and are used as conditions to set values offset from a default in both DynamicPoop() and AnalSpray()


For any poses that have matching poses to the below but with different event names

will need to be patched to the same element as their match as its the element the DP functions use to parse conditions.


For any new pose - can be added to lists, but will need tested: StyleAdjustment are ass up(horizontal) like doggystyle or paf bend over,

although in the DP function directional offsets need parsed if the ass is facing player heading like paf on back. 


 StyleNonAdjustment are just fine tuned positional at a spawn point that I felt certain poses needed. Anything not on the list uses default values.

  this list only is used if the above list is not


 StyleAdjustmentAp is solely for Anal Spray and are ass up spray - away from player, but may spray in same heading like paf on back vs bend over..

\;

 

Function CreateStyleAdjustment(Bool Recreate = False) ; DynamicPoop styleAdjustments
    if  Recreate || StyleAdjustment.Length != 11
        StyleAdjustment = New String[11]
        StyleAdjustment[0] = "paf_pose0"
        StyleAdjustment[1] = "paf_ZazAPC205"
        StyleAdjustment[2] = "paf_pose1"
        StyleAdjustment[3] = "PAF_Bendover01"
        StyleAdjustment[4] = "GS365"
        StyleAdjustment[5] = "GS366"
        StyleAdjustment[6] = "GS404"
        StyleAdjustment[7] = "GS485"
        StyleAdjustment[8] = "GS532"
        StyleAdjustment[9] = "GS542"
        StyleAdjustment[10] = "paf_ZazAPC211"
    endif
EndFunction

 

Function CreateStyleAdjustmentAp(Bool Recreate = False)  ; AnalSpray style adjustments 
    if  Recreate || StyleAdjustmentAp.Length != 13
        StyleAdjustmentAp = New String[13]
        StyleAdjustmentAp[0] = "paf_ZazAPC209"
        StyleAdjustmentAp[1] = "paf_ZazAPC205"
        StyleAdjustmentAp[2] = "paf_pose1"
        StyleAdjustmentAp[3] = "PAF_Bendover01"
        StyleAdjustmentAp[4] = "GS485"
        StyleAdjustmentAp[5] = "GS532"
        StyleAdjustmentAp[6] = "GS505"
        StyleAdjustmentAp[7] = "GS510"
        StyleAdjustmentAp[8] = "GS304"
        StyleAdjustmentAp[9] = "GS404"
        StyleAdjustmentAp[10] = "GS509"
        StyleAdjustmentAp[11] = "paf_pose0"
        StyleAdjustmentAp[12] = "paf_ZazAPC211"
    endif
EndFunction

 

Function CreateStyleNonAdjustment(Bool Recreate = False) ; DynamicPoop Non styleAdjustments
    if  Recreate || StyleNonAdjustment.Length != 6
        StyleNonAdjustment = New String[6]
        StyleNonAdjustment[0] = "paf_ZazAPC201"
        StyleNonAdjustment[1] = "paf_ZazAPC202"
        StyleNonAdjustment[2] = "GS11"
        StyleNonAdjustment[3] = "GS12"
        StyleNonAdjustment[4] = "GS497"
        StyleNonAdjustment[5] = "GS406"
    endif
EndFunction

 

Edited by Dg75

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
×
×
  • Create New...