Jump to content

Recommended Posts

7 hours ago, -Caden- said:

sure, I have never actually played this mod, so all I did was change  conditions and fix issues I saw, made it race aware, gender aware and all that

 

When you play it , tell me, causer I don't play it, or you can go in and make the changes, anyone can

Thanx for the update

I was hoping for this to work on female aproach male pros, but what is happening now is a lot of gay/lesbian aproaches, thats ok but i was hoping for the FM NPC thing to happen though.....did not try the update on a new game

 

In an earlier discussion on this thread some people mentioned that the mod was a mess and should be rewritten from scracth... but as i use it as a core-mod (NPC/NPC thing) im glad for your updates. Im not using the home deliveries because of the sometimes SL difficult enviroments, closed doors(trespassing) etc

The TDF mod has this dance allure/strip function i would wish this mod had as well:classic_angel:https://www.nexusmods.com/skyrim/mods/100826?tab=posts&BH=0

Link to comment

Hello, I enjoy your mod but have only been using nomkaz's conversation since I only have SE. I asked on the support thread if anyone had seen npcs approach male npc prostitutes but no one was able to give an answer.

I have noticed that npcs solicit with other npcs but only male on female. I created some male prostitutes, currently I am able to solicit them myself but npcs don't. Is this possible?

Link to comment
15 minutes ago, fuckmyshit said:

Hello, I enjoy your mod but have only been using nomkaz's conversation since I only have SE. I asked on the support thread if anyone had seen npcs approach male npc prostitutes but no one was able to give an answer.

I have noticed that npcs solicit with other npcs but only male on female. I created some male prostitutes, currently I am able to solicit them myself but npcs don't. Is this possible?

meetoo

Link to comment
2 hours ago, iggypop1 said:

Thanx for the update

I was hoping for this to work on female aproach male pros, but what is happening now is a lot of gay/lesbian aproaches, thats ok but i was hoping for the FM NPC thing to happen though.....did not try the update on a new game

 

In an earlier discussion on this thread some people mentioned that the mod was a mess and should be rewritten from scracth... but as i use it as a core-mod (NPC/NPC thing) im glad for your updates. Im not using the home deliveries because of the sometimes SL difficult enviroments, closed doors(trespassing) etc

The TDF mod has this dance allure/strip function i would wish this mod had as well:classic_angel:https://www.nexusmods.com/skyrim/mods/100826?tab=posts&BH=0

Thats why I didnt really want to contunie with this mod, it does need to be re written, this is not my code, dont get me wrong what the poeople before me did, they did well, but 2 or three people worked on this before I did, so sometimes I am chasing my tail on this to figure out why things are not working cause I came into the middle of this and am not sure of everything others have done

1 hour ago, fuckmyshit said:

Hello, I enjoy your mod but have only been using nomkaz's conversation since I only have SE. I asked on the support thread if anyone had seen npcs approach male npc prostitutes but no one was able to give an answer.

I have noticed that npcs solicit with other npcs but only male on female. I created some male prostitutes, currently I am able to solicit them myself but npcs don't. Is this possible?

Next time you see an approach with male on male, please let me know what the dialogue says, it will make it easier for me to chase down what is happening by searching dialogue

1 hour ago, iggypop1 said:

meetoo

Next time you see an approach with male on male, please let me know what the dialogue says, it will make it easier for me to chase down what is happening by searching dialogue

Link to comment
8 minutes ago, -Caden- said:

Thats why I didnt really want to contunie with this mod, it does need to be re written, this is not my code, dont get me wrong what the poeople before me did, they did well, but 2 or three people worked on this before I did, so sometimes I am chasing my tail on this to figure out why things are not working cause I came into the middle of this and am not sure of everything others have done

Next time you see an approach with male on male, please let me know what the dialogue says, it will make it easier for me to chase down what is happening by searching dialogue

Next time you see an approach with male on male, please let me know what the dialogue says, it will make it easier for me to chase down what is happening by searching dialogue

The dialog is the same NPC/NPC. "Oh what are you selling dressed like that?".....etc........so hm! The Male/Female pros works but with the update it allso works for same gender ,FF ,MM ,but just not for Female/Male pros

Link to comment
25 minutes ago, iggypop1 said:

The dialog is the same NPC/NPC. "Oh what are you selling dressed like that?".....etc........so hm! The Male/Female pros works but with the update it allso works for same gender ,FF ,MM ,but just not for Female/Male pros

ok will have a look at it this weekend

Link to comment
2 hours ago, xyzxyz said:

I noticed that I have many $ in the mod menu. That wasn't the case with the older version. Did you change a language setting or something?

And is there a button to disable same-sex NPC-NPC action?

That might be part of not having a clean save and no ther eis no button to shut it off, before anything else happens i need to know that npc, npc sex is working

 

Link to comment
3 hours ago, vetrok said:

 CTD  for SKYRIM LE. The previous version worked.

Which version and have to see if other people are having the issue, don't know why it would CTD by changing dialogue, cause it wont, are you sure you didnt download one of the SE versions?

Link to comment

I Have A Suggestion/Request Which, Rather Than Having 3 Different Versions Of The Mod To Maintain How About Adding A Dialogue Option When You First Register With An Inn Keeper Where The PC Can Request Which Gender Of NPCs They'd Prefer To Service? So Like A Female PC Can Request To Only Service Other Women Or Male PC Can Request To Not Service Other Men?

Link to comment
24 minutes ago, RavinBeast said:

I Have A Suggestion/Request Which, Rather Than Having 3 Different Versions Of The Mod To Maintain How About Adding A Dialogue Option When You First Register With An Inn Keeper Where The PC Can Request Which Gender Of NPCs They'd Prefer To Service? So Like A Female PC Can Request To Only Service Other Women Or Male PC Can Request To Not Service Other Men?

Thats already in MCM in sliders for approach, ad far as homes and gangbangs could add some extra aliases and scripts and make it happen, As I said When I updated this, this is my last update on the mod, permissions are open for everyone, so feel free to ass this if you want

Link to comment

Many thanks for posting both LE and SE versions here, after asking my earlier questions I came to realisation that Nomkaz's conversation might be outdated and F/M NPCs may have been impossible in the version I had. I wish you luck in whatever other mods you are working on

Link to comment
1 hour ago, fuckmyshit said:

Many thanks for posting both LE and SE versions here, after asking my earlier questions I came to realisation that Nomkaz's conversation might be outdated and F/M NPCs may have been impossible in the version I had. I wish you luck in whatever other mods you are working on

Thank you

Link to comment

Ok tested some more with the update...I had one incident where a male hooker got  approached by a female NPC the thing is that it was Brenuin the drunk beggar i had given tavern clothes  and he was using female animations

 

The mod i use that gives all those male in tavern clothes called "Laborers"https://www.nexusmods.com/skyrim/mods/73315?tab=files and the female that approached Brenuin was a female introduced by the same mod  so maybe there is something with this mod?!?....dunno not a big thing though

 

 

Link to comment
1 hour ago, iggypop1 said:

Ok tested some more with the update...I had one incident where a male hooker got  approached by a female NPC the thing is that it was Brenuin the drunk beggar i had given tavern clothes  and he was using female animations

 

The mod i use that gives all those male in tavern clothes called "Laborers"https://www.nexusmods.com/skyrim/mods/73315?tab=files and the female that approached Brenuin was a female introduced by the same mod  so maybe there is something with this mod?!?....dunno not a big thing though

 

 

ok thanks for the info. knowing about the female animation thing might help cause it might help me pin it down in the handler script, this mod has all the sex and rewards in one script


 

Spoiler

 

Scriptname mf_Handler extends Quest  

SexLabFramework Property SexLab Auto

mf_Handler_Config Property HandlerConfig Auto
mf_Variables Property HandlerConditional Auto

ImageSpaceModifier Property FadeIn  Auto  
ImageSpaceModifier Property FadeOut  Auto  
ImageSpaceModifier Property BlackScreen  Auto  

Message Property ErrorMessage  Auto 

Armor Property WenchCloths  Auto  
Armor Property WenchBoots  Auto  
MiscObject Property Gold  Auto 
; ------ SERVING FOOD QUEST ------------------
MF_FoodJob Property FoodJob Auto
Quest Property SimplerJob  Auto  
mf_simplerjobscript Property SimplerJobScript  Auto  
float TimeLastJobFailed = 0.0
float TimeLastFailJob = 0.0
; ------ FREE ROAMING PROSTITUTION QUEST -----
Quest Property SingleJobMonitor Auto
mf_SolicitPlayerMainScript Property SingleJobMonitorScript Auto
mf_SimpleJobQuestScript Property SingleJob Auto
mf_SimpleJobQuestScript Property SingleJobScript Auto
String akJobType
int totalReward = 0
; ------ HOME DELIVERY QUEST -----------------
MF_RandomQuest Property HomeJob Auto
FormList Property HomeJobs  Auto  
float TimeLastHomeJobCompleted
; ------ MILITARY CAMP QUEST -----------------
MF_RandomQuest Property CampJob Auto
FormList Property CampJobs  Auto
float TimeLastCampJobCompleted
; ------ RANDOM JOB QUEST --------------------
FormList Property RandomQuests Auto
MF_RandomQuest currentQuest
float TimeLastRandomJobCompleted

GlobalVariable Property UndeclaredJobs Auto
GlobalVariable Property TotalClients  Auto
GlobalVariable Property MissingMoney  Auto  
Faction Property ProstituteFaction Auto
Faction Property MadameFaction  Auto 

SPELL Property RefractoryS Auto
SPELL Property RefractoryD Auto

FormList Property BeastRace Auto
FormList Property ElfRace Auto
FormList Property HumanRace Auto

ReferenceAlias Property akPlayerRef Auto
Actor Property akPlayer Auto
int Property PlayerRace Auto

Actor Property akMadame Auto

float Property BountyMult = 1.0 Auto

int lastHomeJob = 0
int lastCampJob = 0
int lastRandomJob = 0

;Frostfall things
bool isFrostfallLoaded = false
GlobalVariable  property Frostfall_exposurePoints = none  auto

SexLabFramework Function GetSexLab()
    return SexLab
endFunction

Actor Function GetPlayer()
    return akPlayer
endFunction

int Function GetScanInterval()
    return HandlerConfig.ScanInterval as int
endFunction

int Function GetMaxRepetitions()
    return (HandlerConfig.MaxRepetitions + 1) as int   ;WS note - the +1 is because of a mismatch between the MCM descriptions and how the scripts use the MaxRepetitions var. (as far as scripts are concerned, a single sex scene is already 1 repetition)
endFunction

Function AddInitClothes()
    HandlerConditional.GotClothes = true

    int config = JValue.readFromFile("Data/MF_RP_Config.json")

    if(config != 0)
        form chestPiece = JValue.solveForm(config, ".startCloths.chestPiece")
        akPlayer.addItem(chestPiece,1)

        int rest = JValue.solveObj(config, ".startCloths.rest")
        int count  = JArray.count(rest)
        while(count >= 0 )
            count -= 1
            akPlayer.addItem(JArray.getForm(rest,count),1)    
        endWhile
        JValue.release(rest)
        JValue.release(config)
    else
        akPlayer.addItem(WenchCloths,1)
        akPlayer.addItem(WenchBoots,1)
    endIf
endFunction

Function ModBountyMult(int point)
    if(point < 0)
        BountyMult -= HandlerConfig.BountyDownRate * point
    else
        BountyMult += HandlerConfig.BountyUpRate * point
    endif
    
    if(BountyMult < 1.0)
        BountyMult = 1.0
    elseif(BountyMult > HandlerConfig.MaxBountyMult)
        BountyMult = HandlerConfig.MaxBountyMult
    endif
endFunction


int Function ValidateStatInt(string statName, int localValue, int modLocValue)
    if(SexLab.FindStat(statName) == -1)
        int value = localValue + modLocValue
        SexLab.RegisterStat(statName, value as string) 
        return value
    else
        return SexLab.AdjustBy(statName, modLocValue)
    endif
endFunction


Function TriggerFailCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastFailJob = Utility.GetCurrentGameTime()
    HandlerConditional.FailJobOnCD = 1
endFunction


Function TriggerHomeJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastHomeJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.HomeJobOnCD = 1
endFunction


Function TriggerCampJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastCampJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.CampJobOnCD = 1
endFunction


Function TriggerRandomJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastRandomJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.RandomJobOnCD = 1
endFunction


Function ResetAllCD()
    HandlerConditional.FailJobOnCD = 0
    HandlerConditional.HomeJobOnCD = 0
    HandlerConditional.CampJobOnCD = 0
    HandlerConditional.RandomJobOnCD = 0
    UnregisterForUpdateGameTime()
endFunction


Event OnUpdateGameTime()
    float time = Utility.GetCurrentGameTime()

    if(TimeLastFailJob +  HandlerConfig.FailJobCD <= time)
    HandlerConditional.FailJobOnCD = 0
    endif
    if(TimeLastHomeJobCompleted + HandlerConfig.HomeJobCD <= time)
    HandlerConditional.HomeJobOnCD = 0
    endif
    if(TimeLastCampJobCompleted + HandlerConfig.CampJobCD <= time)
    HandlerConditional.CampJobOnCD = 0
    endif
    if(TimeLastRandomJobCompleted + HandlerConfig.RandomJobCD <= time)
    HandlerConditional.RandomJobOnCD = 0
    endif

    ;if all of them are off CD, stop receiving events
    if(HandlerConditional.FailJobOnCD == 0 && HandlerConditional.HomeJobOnCD == 0 && HandlerConditional.CampJobOnCD == 0 && HandlerConditional.RandomJobOnCD == 0)
    UnregisterForUpdateGameTime()
    endif
endEvent


Function SetMadame(Actor Madame, int rank)
    akPlayer = akPlayerRef.GetRef() as Actor
    Race pRace = akPlayer.GetActorBase().GetRace()
    if(HumanRace.HasForm(pRace))
        PlayerRace = 1
    elseif(ElfRace.HasForm(pRace))
        PlayerRace = 2
    elseif(BeastRace.HasForm(pRace))    
        PlayerRace = 4
    else
        PlayerRace = 8
    endif

    akMadame = Madame
    akMadame.SetFactionRank(MadameFaction, rank)
    akPlayer.SetFactionRank(MadameFaction, 0) ; just put the player in madame_faction such that we know by looking at ourselves that we are running a quest for a madame

    UndeclaredJobs.SetValue(0)
    ; ...
endFunction


Function Reset()
    akPlayer = akPlayerRef.GetRef() as Actor
    akPlayer.RemoveFromFaction(MadameFaction)
    if(akMadame != None)
     akMadame.SetFactionRank(MadameFaction, 0)
    endif
    ; WS edit - replacing foodjob with simplerjob
    ;FoodJob.Stop()
    SimplerJob.Stop()

    SingleJob.Stop()

    if(HomeJob)
        HomeJob.Stop()
    endif

    if(CampJob)
        CampJob.Stop()
    endif

    if(currentQuest)
        currentQuest.Stop()
    endif
    
    ResetAllCD()
endFunction


Function ResetMadame()
    int tc = TotalClients.GetValueInt()
    if(tc < HandlerConfig.ProstituteRank1)
        akPlayer.SetFactionRank(ProstituteFaction, 0)
    elseif(tc <  HandlerConfig.ProstituteRank2)
        akPlayer.SetFactionRank(ProstituteFaction, 1)
    elseif(tc <  HandlerConfig.ProstituteRank3)
        akPlayer.SetFactionRank(ProstituteFaction, 2)
    elseif(tc <  HandlerConfig.ProstituteRank4)
        akPlayer.SetFactionRank(ProstituteFaction, 3)
    elseif(tc <  HandlerConfig.ProstituteRank5)
        akPlayer.SetFactionRank(ProstituteFaction, 4)
    else
        akPlayer.SetFactionRank(ProstituteFaction, 5)
    endif

    int pr = akPlayer.GetFactionRank(ProstituteFaction)
    if(pr >= 1 && HandlerConditional.PlayerKnowsHomeJob != 1)
        HandlerConditional.PlayerLearnHomeJob = 1
    endif
    if(pr >= 2 && HandlerConditional.PlayerKnowsCampJob != 1)
        HandlerConditional.PlayerLearnCampJob = 1
    endif
    if(pr >= 3 && HandlerConditional.PlayerKnowsRandomJob != 1)
        HandlerConditional.PlayerLearnRandomJob = 1
    endif

    akMadame.SetFactionRank(MadameFaction, 0)
    akPlayer.RemoveFromFaction(MadameFaction)
endFunction


; ------------ QUEST KICKERS --------------
Function SimplerJobQuestKicker(Actor Madame)
    ; WS edit - replacing foodjob with simplerjob
    ;FoodJob.Start()
    ;FoodJob.setMadame(Madame)
    SimplerJob.Start()
    SetMadame(Madame, 1)
endFunction


Function SingleJobMonitorKicker(Actor Madame)
    SingleJob.Start()
    SingleJob.SetStage(0)
    SingleJob.ResetVariables()
    SetMadame(Madame, 2)
endFunction

Function SingleJobQuestKicker(Actor Client, bool once = false)    
    SingleJobScript.Start()
    SingleJobScript.SetOnce(once)
    SingleJobScript.ForceSpeakerClient(Client)
endFunction


Function SingleJobQuestKickerAndApproach(Actor Client)
    SingleJobQuestKicker(Client)
endFunction

Function HomeJobQuestKicker(Actor Madame)
    HomeJob = QuestKicker(HomeJobs,lastHomeJob)

    if(HomeJob)
        HomeJob.setMadame(Madame)
        SetMadame(Madame, 3)
    endif
endFunction

Function CampJobQuestKicker(Actor Madame)
    CampJob = QuestKicker(CampJobs,lastCampJob)

    if(CampJob)
        CampJob.setMadame(Madame)
        SetMadame(Madame, 4)
    endif
endFunction

Function RandomJobQuestKicker(Actor Madame)
    currentQuest = QuestKicker(RandomQuests,lastRandomJob)
    
    if(currentQuest)
        currentQuest.setMadame(Madame)
        SetMadame(Madame, 5)
    endif
endFunction


; ------------- QUEST FAILURE --------------

; WS edit - adding functions for SimplerJob
Function SimplerJobQuestFail()
    ResetMadame()
    TriggerFailCD()
    SimplerJob.Stop()
endFunction

; WS edit - adding functions for SimplerJob
Function SimplerJobLeave()
    if(SimplerJob.GetStage() == 20 || SimplerJob.GetStage() == 30); food or gold
        Debug.Notification("You left the inn with the innkeeper's property")
        TriggerFailCD()
    
        ; consequence ??
        int amount = (100.0 * BountyMult) as int
        akMadame.GetCrimeFaction().ModCrimeGold(amount)
        Debug.Notification(amount+"gold bounty added")
        ModBountyMult(1)
    else
        Debug.Notification("You quitted serving food at the inn")
    endif

    ResetMadame()    
    SimplerJob.Stop() 
    SingleJob.Stop()
endFunction

Function SingleJobQuestFail()
    SingleJob.Stop()
endFunction


Function SingleJobLeave()
    if(UndeclaredJobs.GetValue() > 0)
        Debug.Notification("You left town with the innkeeper's gold")
        TriggerFailCD()

        ; consequence ??
        int amount =  (BountyMult * (UndeclaredJobs.GetValueInt() * HandlerConfig.BaseGoldPerClient * HandlerConfig.BaseGoldMadameCut * BountyMult) / 100.0) as int
        akMadame.GetCrimeFaction().ModCrimeGold(amount)
        Debug.Notification(amount+" gold bounty added")
        ModBountyMult(1)
    else
        Debug.Notification("You left the prostitution job behind you")
    endif

    ResetMadame()
    UndeclaredJobs.SetValue(0)
    SingleJob.CompleteAllObjectives()
    SingleJob.StopFollow()
    SingleJob.Stop()
endFunction


Function HomeJobQuestFail()
    HomeJob.FailAllObjectives()
    HomeJob.SetStage(201)     ;to get the quest fail message
    EndHomeJob()              ;this will ensure the homeJob CD is triggered, and that the quest's shutdown stage is called, and also calls ResetMadame()
endFunction


Function CampJobQuestFail()
    CampJob.FailAllObjectives()
    CampJob.SetStage(201)     ;to get the fail message
    endCampJob()
endFunction


Function RandomJobQuestFail()
    ResetMadame()
    TriggerRandomJobCD()
    currentQuest.FailAllObjectives()
    currentQuest.setStage(200)
    currentQuest.Stop()
    currentQuest = None
endFunction

;
; ---------- FOOD JOB REWARD - WS added
;
Function GetSimplerJobReward(bool success = true)
    if(success)
        SimplerJobScript.GetTip()
    endif
    ResetMadame() 
    SimplerJob.Stop()
endFunction

;
; ----------- SINGLE JOB REWARD -------------
;
Function GetSingleJobReward(int lie)
    int amount

    if (lie == 0)
        amount =  Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 100)
        ModBountyMult(UndeclaredJobs.GetValueInt() * (-1))
    elseif (lie == 1) 
        amount =  Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 1000)
    elseif (lie > 1)
        amount = Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 33)
        akMadame.GetCrimeFaction().ModCrimeGold(Math.floor(amount * BountyMult))
        Debug.Notification("The innkeeper put a bounty on my head, I'll have to sort that out with the guards")
        ModBountyMult(1)
        TriggerFailCD()
        amount = 0
    endif
    
    totalReward = 0;

    if(amount != 0)
        int goldCount = Game.GetPlayer().GetItemCount(Gold)
        if(goldCount < amount)
            amount -= goldCount
            MissingMoney.mod(amount)
            UpdateCurrentInstanceGlobal(MissingMoney) 
            amount = goldCount
        endIf
        akMadame.AddItem(Gold, amount)
        akPlayer.RemoveItem(Gold,  amount)
    endif

    ResetMadame()
    UndeclaredJobs.SetValue(0)
    SingleJobMonitor.Stop()
    SingleJob.UnregisterForUpdate()
    SingleJob.Stop()
    
    ;Finish misc quest for learning about prostitution if present
    If IsObjectiveDisplayed(10)
        SetObjectiveCompleted(10)
    EndIf
endFunction


int Function CalcReward(float QM = 1.0, float PERF = 1.0, string Type = "All",int repetitions=1)
    float BG = HandlerConfig.BaseGoldPerClient ; base cost
    float SM = akPlayer.GetAV("Speechcraft") * HandlerConfig.GoldBonusPerSpeechcraft ; speechcraft modifier
    float FM = akPlayer.GetFactionRank(ProstituteFaction) * HandlerConfig.GoldBonusPerRank ; faction reputation modifier
    float GM = 0.0

    if(Game.GetPlayer().GetActorBase().GetSex() == 1)
        GM = HandlerConfig.FemaleGoldBonus
    else
        GM = HandlerConfig.MaleGoldBonus
    endif

    float MOD
    float PM
    if(Type == "Oral" || Type == "Blowjob" || Type == "Cunnilingus")
        MOD = HandlerConfig.OralModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Oral") 
    elseif(Type == "Anal")
        MOD = HandlerConfig.AnalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Anal") 
    elseif(Type == "Vaginal")
        MOD = HandlerConfig.VaginalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Vaginal") 
    elseif(Type == "Rape")
        MOD = HandlerConfig.RapeModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Victim") 
    elseIf(Type == "Lesbian")
        MOD = HandlerConfig.VaginalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Vaginal") 
    else
        MOD = 1.0 ; overall quest modifier
        PM =   HandlerConfig.GoldBonusPerSexRank * (SexLab.GetPlayerStatLevel("Anal") + SexLab.GetPlayerStatLevel("Vaginal") + SexLab.GetPlayerStatLevel("Oral"))/3
    endif

    MOD *= PERF * QM

    int payment = Math.Floor((BG + SM + FM + PM + GM) * MOD)

    if(repetitions > 1)
        int multipleBonus=  Math.Floor(payment * (repetitions - 1) * HandlerConfig.MultipleBonus)
        payment = payment + multipleBonus
    endif

    return     payment
endFunction

;
; ----------- HOME JOB REWARD -------------
;
Function GetHomeJobReward()
    float PERF = HandlerConditional.PerformanceRewardMod
    float QM = 3.0 * HandlerConfig.HomeDeliveryQuestModifier

    akPlayer.AddItem(Gold, CalcReward(QM, PERF))
    HomeJob.CompleteAllObjectives()
    EndHomeJob()
endFunction

Function EndHomeJob()
    HomeJob.Stop()
    ModBountyMult(-2)
    ResetMadame()    
    TriggerHomeJobCD()
endFunction

;
; ----------- CAMP JOB REWARD -------------
;
Function GetCampJobReward()
    float PERF = (CampJob as mf_CampJobQuestScript).GetModifier() ; overall quest modifier
    float QM = 0.75 * HandlerConfig.CampJobQuestModifier

    ModBountyMult(-PERF as int)
    
    akPlayer.AddItem(Gold, CalcReward(QM, PERF))
    CampJob.CompleteAllObjectives()
    endCampJob()
endFunction

Function endCampJob()
    ResetMadame()    
    TriggerCampJobCD()
    CampJob.stop()
endFunction
;
; ----------- RANDOM JOB REWARD -------------
;
Function GetRandomJobReward()
    ModBountyMult(-5)
    ResetMadame()    
    TriggerRandomJobCD()
    currentQuest.Stop()
    currentQuest = None
    HandlerConditional.GrantExtraReward = false;
endFunction

Function GetRandomJobExtraReward()
    ModBountyMult(-5)
    ResetMadame()    
    TriggerRandomJobCD()
    (currentQuest as MF_RandomQuest).getExtraReward()
    currentQuest.Stop()
    currentQuest = None
    HandlerConditional.GrantExtraReward = false;
endFunction

;
; ----------- REWARD FROM CLIENT -------------
;
Function GetRewardSingleFromClient(Actor akClient, int repetitions=0, int jobNumeric = -1)
    float PERF = HandlerConditional.PerformanceRewardMod
    float QM = 1.0

    string jobType= akJobType
    if(jobNumeric == 1)
        jobType= "Oral"
    elseif(jobNumeric == 2)
        jobType= "Vaginal"
    elseif(jobNumeric == 3)
        jobType= "Anal"
    elseif(jobNumeric == 4)
        jobType= "Things"
    elseif(jobNumeric == 5)
        jobType= "Rape"
    elseif(jobNumeric == 7)
        jobType= "Lesbian"
    endIf


    if(repetitions > 0)
        int reward = CalcReward(QM, PERF, jobType,repetitions)
        totalReward += reward
        akPlayer.AddItem(Gold, reward)
        int t = UndeclaredJobs.GetValueInt() + 1
        UndeclaredJobs.SetValue(t)
        UpdateCurrentInstanceGlobal(UndeclaredJobs)
    endif
endFunction

event EvaluateSex(string eventName, string argString, float argNum, form sender)
    CalcRewardMod(argString)
    ; Debug.Notification("Sex lasted " + sexLasted + " sec")
    UnregisterForModEvent("AnimationEnd_GetTime") 
endEvent

Function CalcRewardMod(string argString)
    float sexLasted = SexLab.HookTime(argString)

    if(sexLasted > HandlerConfig.TimeForFullReward)
        HandlerConditional.PerformanceRewardMod = 1.0
    else
         HandlerConditional.PerformanceRewardMod = sexLasted / HandlerConfig.TimeForFullReward
    endif


endFunction


Function IncrementTotalClients(int c)
    int t = TotalClients.GetValueInt()
    TotalClients.SetValue(ValidateStatInt("Client Count", t, c))
    UpdateCurrentInstanceGlobal(TotalClients)
endFunction


Function SetRefractory(Actor Client, bool satisfied=true)
    if(satisfied)
        RefractoryS.Cast(Client, Client)
    else
        RefractoryD.Cast(Client, Client)
    endIf
endFunction


sslThreadController Function PerformSex(Actor akClient, string type, string aggr = "None", string next = "None",bool isPlayerVictim=false, bool foreplay=false, bool switchOnFF =false)

    sslBaseAnimation[] anims

    actor[] actors = new actor[2]
    int playerIndex =0
    actors[0] = akPlayer
    actors[1] = akClient
    
    int sex0 = actors[0].GetActorBase().GetSex()
    int sex1 = actors[1].GetLeveledActorBase().GetSex() 

    int f  = sex0 + sex1
    int m = 2 - f

    string option = ""
    string suppress ="Aggressive"
    if(aggr != "None" || isPlayerVictim)
        option = ",Aggressive"
        suppress =""
    endif

    ; sort the player/client depending on the anim type that will be chosen
    if(f == 2); FF
        option = ""
        suppress ="Aggressive"
        if(type == "Oral" && !switchOnFF)
            actors[0] = akClient
            actors[1] = akPlayer
            playerIndex=1
        elseif(switchOnFF)
            actors[0] = akClient
            actors[1] = akPlayer
            playerIndex=1
        endif
        
        ;ws edit - searching by "FF,<type>" when type=oral removes a lot of valid cunnilingus animations - search for tag cunnilingus instead, with 69 suppress 
        if type == "Oral"
            anims = SexLab.GetAnimationsByTags(2, "Cunnilingus", "69", requireAll=true)
        Else
            ;if type isn't Oral, then use the code that was already here
            anims = SexLab.GetAnimationsByTags(2, "FF,"+ type+ option,suppress, requireAll=true)
        EndIf

        if(anims.Length == 0)
            anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress, requireAll=true)
        endif
    elseif(f == 1);FM || MF
        if(sex0 == 0) ;PC is male
            actors[0] = akPlayer
            actors[1] = akClient
            playerIndex=1
        endif
        anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress+",69", requireAll=true)
    else; MM
        anims = SexLab.GetAnimationsByTags(2, "MM,"+ type+ option,suppress, requireAll=true)
        if(anims.Length == 0)
            anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress, requireAll=true)
        endif
    endif


    if(anims.Length == 0)
        Debug.Notification("You've blacklisted all consensual "+type+" sex anims. This won't work.")
        anims = SexLab.GetAnimationsByTags(2,"Sex")
    endif

    SetRefractory(akClient)

    return fuck(actors,playerIndex,anims,foreplay,next,type,isPlayerVictim).StartThread()
    
endFunction

sslThreadModel Function fuck(Actor[] actors, int playerIndex, sslBaseAnimation[] anims, bool foreplay = true, string next = "None",string type = "None", bool isPlayerVictim = false)

    akJobType = type
    IncrementTotalClients(1)

    bool[] equip0 = New bool[33]
    bool[] equip1 = New bool[33]
    int i=0
    While(i < 33)
        equip0 = false
        equip1 = false
        i += 1
    endWhile

    if(type == "Oral")
        equip0[0] = true ;head
        equip0[3] = true ;hand
        equip0[4] = true ;forearms
        equip0[9] = true ;shield
        equip0[14] = true ;face
        equip0[32] = true ;weapon

        equip1[2] = true ;body
        equip1[9] = true ;shield
        equip1[16] = true ;chest
        equip1[19] = true ;pelvis
        equip1[28] = true ;undergarment
        equip1[32] = true ;weapon    
    else
        equip0[2] = true ;body
        equip0[9] = true ;shield
        equip0[16] = true ;chest
        equip0[19] = true ;pelvis
        equip0[28] = true ;undergarment
        equip0[32] = true ;weapon    

        equip1[2] = true ;body
        equip1[9] = true ;shield
        equip1[16] = true ;chest
        equip1[19] = true ;pelvis
        equip1[28] = true ;undergarment
        equip1[32] = true ;weapon    
    endif

    RegisterForModEvent("AnimationEnd_GetTime", "EvaluateSex")
    While (SexLab.FindActorController(actors[0]) != -1 || SexLab.FindActorController(actors[1]) != -1)
        Utility.Wait(1.0)
    endwhile

    sslThreadModel th = SexLab.NewThread()
    if(actors.length == 2)
        if(playerIndex == 1)
            th.AddActor(actors[0])
            th.AddActor(actors[1], isVictim= isPlayerVictim)
            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[1], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
            endif
        else
            th.AddActor(actors[0], isVictim= isPlayerVictim)
            th.AddActor(actors[1])

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[0], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[1], equip1)
            endif
        endif
    elseif(actors.length == 3)
        if(playerIndex == 0)
            th.AddActor(actors[0], isVictim= isPlayerVictim)
            th.AddActor(actors[1])
            th.AddActor(actors[2])

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[0], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[1], equip1)
                th.SetStrip(actors[2], equip1)
            endif
        elseif(playerIndex == 1)
            th.AddActor(actors[0])
            th.AddActor(actors[1], isVictim= isPlayerVictim)
            th.AddActor(actors[2])
            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[1], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
                th.SetStrip(actors[2], equip1)
            endif
        elseif(playerIndex == 2)
            th.AddActor(actors[0])
            th.AddActor(actors[1])
            th.AddActor(actors[2], isVictim= isPlayerVictim)

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[2], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
                th.SetStrip(actors[1], equip1)
            endif
        endif
    endIf
    th.SetAnimations(anims)
    if(isPlayerVictim)
        th.DisableLeadIn(true) 
    else
        th.DisableLeadIn(!foreplay) 
    endif
    ;Bed Search is Disabled if a CenterObject is set
    ;if(!HandlerConfig.UseBeds)    ;ws - commented out - this might be what's causing issues with the automatic free cam (edit: it was!)
    ;    th.CenterOnObject(actors[playerIndex])
    ;endIf
    ;WS - restoring UseBeds MCM function
    If(!HandlerConfig.UseBeds) 
        th.DisableBedUse(true)
    EndIf
    th.SetHook("GetTime")
    if(next != "None")
        th.SetHook(next)
    endif
    return th

endFunction


sslThreadController Function PerformCreatureSex(Actor[] creatures, string next = "None")
    sslThreadModel th = SexLab.NewThread()
    th.AddActor(akPlayer, isVictim=true)
    int count = 0
    while count < creatures.length
        th.AddActor(creatures[count])
        count= count+1
    endWhile

    if(next != "None")
        th.SetHook(next)
    endif
    th.CenterOnObject(akPlayer)
    return th.StartThread()    
endFunction

sslThreadController Function PerformThreesome(Actor akClient, Actor akGuest, string next = "None", bool isPlayerVictim =false)
     IncrementTotalClients(2)
     SetRefractory(akClient)
     SetRefractory(akGuest)

     sslBaseAnimation[] anims
     actor[] actors = new actor[3]
     int playerIndex =0
     actors[0] = akPlayer
     actors[1] = akClient
     actors[2] = akGuest

     int sex0 = Game.GetPlayer().GetActorBase().GetSex()
     int sex1 = akClient.GetLeveledActorBase().GetSex() 
     int sex2 = akGuest.GetLeveledActorBase().GetSex() 
     
     int c = 1
     sslBaseAnimation[] anims2
     
     int f  = sex0 + sex1 + sex2
     int m = 3 - f

     if(sex0 == 1) ; female PC
        if(sex1 == 1); female NPC
            if(sex2 == 1); FFF
                c = 2
                anims  = SexLab.GetAnimationsByTags(2, "Cunnilingus")
                if(anims.length ==0)
                    anims  = SexLab.GetAnimationsByTag(2, "FF")
                endif
                if(anims.length ==0)
                    anims  = SexLab.GetAnimationsByTag(2, "MF,FM")
                endif
                anims2 = SexLab.GetAnimationsByTags(1, "F", "Masturbation")
            else
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            endif
        else; male NPC
            if(sex2 == 1) ; FMF
                actors[0] = akGuest
                actors[1] = akPlayer
                actors[2] = akClient
                playerIndex =1
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ;FMM
                anims = SexLab.GetAnimationsByTags(3, "MMF")
            endif
        endif
     else; male PC
        if(sex1 == 1)
            if(sex2 == 1); MFF
                actors[0] = akGuest
                actors[2] = akPlayer
                playerIndex =2
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ; MFM
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            endif
        else
            if(sex2 == 1) ; MMF
                actors[1] = akGuest
                actors[2] = akClient
            
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ;MMM
                anims  = SexLab.GetAnimationsByTags(3, "MMF") ;player in female position
            endif
        endif 
     endif
     
     if(anims.Length == 0)
        Debug.Notification("You've blacklisted all threesome sex anims. This won't work.")
        if(c == 1)
            anims = SexLab.GetAnimationsByTags(3,"Sex")
        else
            anims = SexLab.GetAnimationsByTags(2,"Sex")
            anims2 = SexLab.GetAnimationsByTags(1,"Sex")
        endif
     endif
        RegisterForModEvent("AnimationEnd_GetTime", "EvaluateSex")
        While (SexLab.FindActorController(actors[0]) != -1 ||SexLab.FindActorController(actors[1]) != -1 || SexLab.FindActorController(actors[2]) != -1)
            Utility.Wait(1.0)
        endwhile
        if(c == 1)
            sslThreadModel th = SexLab.NewThread()
            if(playerIndex ==0)    
                th.AddActor(actors[0],isVictim = isPlayerVictim)
                th.AddActor(actors[1])
                th.AddActor(actors[2])
            elseif(playerIndex ==1)
                th.AddActor(actors[0])
                th.AddActor(actors[1],isVictim = isPlayerVictim)
                th.AddActor(actors[2])
            else
                th.AddActor(actors[0])
                th.AddActor(actors[1])
                th.AddActor(actors[2],isVictim = isPlayerVictim)
            endif
            th.SetAnimations(anims)
            th.DisableLeadIn(isPlayerVictim) 
            th.SetHook("GetTime")
            if(next != "None")
                th.SetHook(next)
            endif
            return th.StartThread()
        else
            sslThreadModel th2 = SexLab.NewThread()
            th2.AddActor(actors[1])
            th2.SetAnimations(anims2)
            th2.DisableLeadIn(true) 
            th2.StartThread()    
        
            sslThreadModel th1 = SexLab.NewThread()
            if(playerIndex ==0)    
                th1.AddActor(actors[0],isVictim = isPlayerVictim)
                th1.AddActor(actors[2])
            else
                th1.AddActor(actors[0])
                th1.AddActor(actors[2],isVictim = isPlayerVictim)
            endif
            th1.SetAnimations(anims)
            th1.DisableLeadIn(true) 
            th1.SetHook("GetTime")
            if(next != "None")
                th1.SetHook(next)
            endif
            return th1.StartThread()
        endif
endFunction


sslThreadController Function PerformMasturbation(Actor akSoloer, string next = "None")
 int sex = akSoloer.GetLeveledActorBase().GetSex() 
 
 akJobType = "Masturbation"
 sslBaseAnimation[] anims
 if(sex == 0)
    anims = SexLab.GetAnimationsByTag(1, "M", akJobType,  requireAll=true)    
    ;anims = SexLab.GetAnimationsByTag(1, "M", akJobType, tagSuppress="Zaz", requireAll=true)
 else
    anims = SexLab.GetAnimationsByTag(1, "F", akJobType, requireAll=true)
    ;anims = SexLab.GetAnimationsByTag(1, "F", akJobType, tagSuppress="Zaz", requireAll=true)
 endif 
 
 if(anims.Length == 0)
    Debug.Notification("You've blacklisted all consensual "+akJobType+" sex anims. This won't work.")
    return None
 else
      While (SexLab.FindActorController(akSoloer) != -1 )
        Utility.Wait(1.0)
    endwhile
    sslThreadModel th = SexLab.NewThread()
    th.AddActor(akSoloer)
    th.SetAnimations(anims)
    th.DisableLeadIn(true)
    if(next != "None")
        th.SetHook(next)
    endif
    return th.StartThread()
 endif
endFunction

Function PerformDance()

endFunction

Function FadeToBlack()
    akPlayer.SetRestrained(true)    
    FadeOut.Apply()
    Utility.Wait(2.5) ; since Fadeout lasts exactly 3.0s, we need to allow some script delay
    FadeOut.PopTo(BlackScreen)
endFunction

Function FadeFromBlack()
    BlackScreen.PopTo(FadeIn)    
    Utility.Wait(2.0)        
    FadeIn.Remove()        
    akPlayer.SetRestrained(false)
endFunction

MF_RandomQuest Function QuestKicker(FormList quests,int lastIndex)

    Debug.Trace("[Radiant Prostitution] try to start a quest from list " + quests.GetName())
    Debug.Trace("[Radiant Prostitution] last Index was " + lastIndex)

    MF_RandomQuest questToStart = randomQuest(quests, lastIndex)

    Debug.Trace("[Radiant Prostitution] Try to start Quest " + questToStart)

    int try1 = 0
    While(!questToStart.IsRunning() && try1 < 5)
        int try2 = 0
        Debug.Trace("[Radiant Prostitution] Are Preconditions fullfilled ? " + (questToStart.checkConditions()))
        if(questToStart.checkConditions())
            questToStart.Start() 
            Utility.wait(0.5)
            While(!questToStart.IsRunning() && try2 < 5)
                Debug.Trace("[Radiant Prostitution] Quest not started Retry "+ try2)
                questToStart.Start()
                try2 += 1
                Utility.wait(0.5)
            endWhile
        endIf
        if(!questToStart.IsRunning())
            Debug.Trace("[Radiant Prostitution] Quest did not start get a new one")
            questToStart = randomQuest(quests, lastIndex)
            Debug.Trace("[Radiant Prostitution] New Quest is "+ questToStart)
            questToStart.Start() 
            try1 += 1
        endIf
    endWhile

    if(questToStart.IsRunning())
        Debug.Trace("[Radiant Prostitution] Quest started")
        return questToStart
    endif
    
    Debug.Trace("[Radiant Prostitution] no Quest Could be started")
    Debug.Notification("No quest was started. Please try again.")
    return none
endFunction

MF_RandomQuest Function randomQuest(FormList quests, int lastIndex)

    int listSize = quests.GetSize()
    
    if(listSize <= 0)
        ErrorMessage.show()
    endIf

    ; WS - commented out, this method of picking a quest confuses me and seems to cause predictable repetition even after the first round
    ;lastIndex = lastIndex + Utility.RandomInt(1, Math.ceiling(listSize / 2))
    ;while(lastIndex > listSize - 1)
    ;    lastIndex = lastIndex - (listSize - 1)
    ;endWhile
    
    
    ; WS - instead of the above whatever-the-hell-that-is, all we want is ensure that a random quest isn't given twice in a row, if there are more than 2 choices
    ; note: the WHILE needs to check if listSize is larger than one, so we don't get stuck if the list only has 1 quest
    ; and if the listSize is 2, we need to do RandomInt(0,1) instead, otherwise it'll always alternate between one and the other with no randomness
    int newIndex = lastIndex
    if listSize == 2
        newIndex = Utility.RandomInt(0,1)
    Else
        While ( (newIndex == lastIndex) && (listSize > 1) )
            newIndex = Utility.RandomInt(0, (listSize - 1))
        EndWhile
    EndIf

    Debug.Trace("MF_RP TRACE : FINAL INDEX IS " + newIndex + " (" + quests.GetAt(newIndex) + ")")
    MF_RandomQuest questToStart = quests.GetAt(newIndex) as MF_RandomQuest

    if(questToStart.getRank() == 1)
        lastHomeJob = newIndex
    elseif(questToStart.getRank() == 2)
        lastCampJob = newIndex
    elseif(questToStart.getRank() >= 3)
        lastRandomJob = newIndex
    endIf

    return questToStart
endFunction


Function loadFrostfall()
    isFrostfallLoaded = false
    int Mods = Game.GetModCount()
    int i
    While i < Mods
        string Modname = Game.GetModName(i)
        If !isFrostfallLoaded && Modname == "Chesko_Frostfall.esp"
            isFrostfallLoaded = true
            Frostfall_exposurePoints = Game.GetFormFromFile(0x00000183d, "chesko_frostfall.esp") as GlobalVariable
            return
        EndIf
        i += 1
    EndWhile
EndFunction


Function frostfallWarmPlayer()
    if (isFrostfallLoaded)
        Frostfall_exposurePoints.SetValue(120)
    Else
        loadFrostfall()
        If (isFrostfallLoaded)
            Frostfall_exposurePoints.SetValue(120)
        EndIf
    EndIf
EndFunction

 

 

 

Link to comment
1 hour ago, -Caden- said:

ok thanks for the info. knowing about the female animation thing might help cause it might help me pin it down in the handler script, this mod has all the sex and rewards in one script


 

  Reveal hidden contents

 

Scriptname mf_Handler extends Quest  

SexLabFramework Property SexLab Auto

mf_Handler_Config Property HandlerConfig Auto
mf_Variables Property HandlerConditional Auto

ImageSpaceModifier Property FadeIn  Auto  
ImageSpaceModifier Property FadeOut  Auto  
ImageSpaceModifier Property BlackScreen  Auto  

Message Property ErrorMessage  Auto 

Armor Property WenchCloths  Auto  
Armor Property WenchBoots  Auto  
MiscObject Property Gold  Auto 
; ------ SERVING FOOD QUEST ------------------
MF_FoodJob Property FoodJob Auto
Quest Property SimplerJob  Auto  
mf_simplerjobscript Property SimplerJobScript  Auto  
float TimeLastJobFailed = 0.0
float TimeLastFailJob = 0.0
; ------ FREE ROAMING PROSTITUTION QUEST -----
Quest Property SingleJobMonitor Auto
mf_SolicitPlayerMainScript Property SingleJobMonitorScript Auto
mf_SimpleJobQuestScript Property SingleJob Auto
mf_SimpleJobQuestScript Property SingleJobScript Auto
String akJobType
int totalReward = 0
; ------ HOME DELIVERY QUEST -----------------
MF_RandomQuest Property HomeJob Auto
FormList Property HomeJobs  Auto  
float TimeLastHomeJobCompleted
; ------ MILITARY CAMP QUEST -----------------
MF_RandomQuest Property CampJob Auto
FormList Property CampJobs  Auto
float TimeLastCampJobCompleted
; ------ RANDOM JOB QUEST --------------------
FormList Property RandomQuests Auto
MF_RandomQuest currentQuest
float TimeLastRandomJobCompleted

GlobalVariable Property UndeclaredJobs Auto
GlobalVariable Property TotalClients  Auto
GlobalVariable Property MissingMoney  Auto  
Faction Property ProstituteFaction Auto
Faction Property MadameFaction  Auto 

SPELL Property RefractoryS Auto
SPELL Property RefractoryD Auto

FormList Property BeastRace Auto
FormList Property ElfRace Auto
FormList Property HumanRace Auto

ReferenceAlias Property akPlayerRef Auto
Actor Property akPlayer Auto
int Property PlayerRace Auto

Actor Property akMadame Auto

float Property BountyMult = 1.0 Auto

int lastHomeJob = 0
int lastCampJob = 0
int lastRandomJob = 0

;Frostfall things
bool isFrostfallLoaded = false
GlobalVariable  property Frostfall_exposurePoints = none  auto

SexLabFramework Function GetSexLab()
    return SexLab
endFunction

Actor Function GetPlayer()
    return akPlayer
endFunction

int Function GetScanInterval()
    return HandlerConfig.ScanInterval as int
endFunction

int Function GetMaxRepetitions()
    return (HandlerConfig.MaxRepetitions + 1) as int   ;WS note - the +1 is because of a mismatch between the MCM descriptions and how the scripts use the MaxRepetitions var. (as far as scripts are concerned, a single sex scene is already 1 repetition)
endFunction

Function AddInitClothes()
    HandlerConditional.GotClothes = true

    int config = JValue.readFromFile("Data/MF_RP_Config.json")

    if(config != 0)
        form chestPiece = JValue.solveForm(config, ".startCloths.chestPiece")
        akPlayer.addItem(chestPiece,1)

        int rest = JValue.solveObj(config, ".startCloths.rest")
        int count  = JArray.count(rest)
        while(count >= 0 )
            count -= 1
            akPlayer.addItem(JArray.getForm(rest,count),1)    
        endWhile
        JValue.release(rest)
        JValue.release(config)
    else
        akPlayer.addItem(WenchCloths,1)
        akPlayer.addItem(WenchBoots,1)
    endIf
endFunction

Function ModBountyMult(int point)
    if(point < 0)
        BountyMult -= HandlerConfig.BountyDownRate * point
    else
        BountyMult += HandlerConfig.BountyUpRate * point
    endif
    
    if(BountyMult < 1.0)
        BountyMult = 1.0
    elseif(BountyMult > HandlerConfig.MaxBountyMult)
        BountyMult = HandlerConfig.MaxBountyMult
    endif
endFunction


int Function ValidateStatInt(string statName, int localValue, int modLocValue)
    if(SexLab.FindStat(statName) == -1)
        int value = localValue + modLocValue
        SexLab.RegisterStat(statName, value as string) 
        return value
    else
        return SexLab.AdjustBy(statName, modLocValue)
    endif
endFunction


Function TriggerFailCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastFailJob = Utility.GetCurrentGameTime()
    HandlerConditional.FailJobOnCD = 1
endFunction


Function TriggerHomeJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastHomeJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.HomeJobOnCD = 1
endFunction


Function TriggerCampJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastCampJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.CampJobOnCD = 1
endFunction


Function TriggerRandomJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastRandomJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.RandomJobOnCD = 1
endFunction


Function ResetAllCD()
    HandlerConditional.FailJobOnCD = 0
    HandlerConditional.HomeJobOnCD = 0
    HandlerConditional.CampJobOnCD = 0
    HandlerConditional.RandomJobOnCD = 0
    UnregisterForUpdateGameTime()
endFunction


Event OnUpdateGameTime()
    float time = Utility.GetCurrentGameTime()

    if(TimeLastFailJob +  HandlerConfig.FailJobCD <= time)
    HandlerConditional.FailJobOnCD = 0
    endif
    if(TimeLastHomeJobCompleted + HandlerConfig.HomeJobCD <= time)
    HandlerConditional.HomeJobOnCD = 0
    endif
    if(TimeLastCampJobCompleted + HandlerConfig.CampJobCD <= time)
    HandlerConditional.CampJobOnCD = 0
    endif
    if(TimeLastRandomJobCompleted + HandlerConfig.RandomJobCD <= time)
    HandlerConditional.RandomJobOnCD = 0
    endif

    ;if all of them are off CD, stop receiving events
    if(HandlerConditional.FailJobOnCD == 0 && HandlerConditional.HomeJobOnCD == 0 && HandlerConditional.CampJobOnCD == 0 && HandlerConditional.RandomJobOnCD == 0)
    UnregisterForUpdateGameTime()
    endif
endEvent


Function SetMadame(Actor Madame, int rank)
    akPlayer = akPlayerRef.GetRef() as Actor
    Race pRace = akPlayer.GetActorBase().GetRace()
    if(HumanRace.HasForm(pRace))
        PlayerRace = 1
    elseif(ElfRace.HasForm(pRace))
        PlayerRace = 2
    elseif(BeastRace.HasForm(pRace))    
        PlayerRace = 4
    else
        PlayerRace = 8
    endif

    akMadame = Madame
    akMadame.SetFactionRank(MadameFaction, rank)
    akPlayer.SetFactionRank(MadameFaction, 0) ; just put the player in madame_faction such that we know by looking at ourselves that we are running a quest for a madame

    UndeclaredJobs.SetValue(0)
    ; ...
endFunction


Function Reset()
    akPlayer = akPlayerRef.GetRef() as Actor
    akPlayer.RemoveFromFaction(MadameFaction)
    if(akMadame != None)
     akMadame.SetFactionRank(MadameFaction, 0)
    endif
    ; WS edit - replacing foodjob with simplerjob
    ;FoodJob.Stop()
    SimplerJob.Stop()

    SingleJob.Stop()

    if(HomeJob)
        HomeJob.Stop()
    endif

    if(CampJob)
        CampJob.Stop()
    endif

    if(currentQuest)
        currentQuest.Stop()
    endif
    
    ResetAllCD()
endFunction


Function ResetMadame()
    int tc = TotalClients.GetValueInt()
    if(tc < HandlerConfig.ProstituteRank1)
        akPlayer.SetFactionRank(ProstituteFaction, 0)
    elseif(tc <  HandlerConfig.ProstituteRank2)
        akPlayer.SetFactionRank(ProstituteFaction, 1)
    elseif(tc <  HandlerConfig.ProstituteRank3)
        akPlayer.SetFactionRank(ProstituteFaction, 2)
    elseif(tc <  HandlerConfig.ProstituteRank4)
        akPlayer.SetFactionRank(ProstituteFaction, 3)
    elseif(tc <  HandlerConfig.ProstituteRank5)
        akPlayer.SetFactionRank(ProstituteFaction, 4)
    else
        akPlayer.SetFactionRank(ProstituteFaction, 5)
    endif

    int pr = akPlayer.GetFactionRank(ProstituteFaction)
    if(pr >= 1 && HandlerConditional.PlayerKnowsHomeJob != 1)
        HandlerConditional.PlayerLearnHomeJob = 1
    endif
    if(pr >= 2 && HandlerConditional.PlayerKnowsCampJob != 1)
        HandlerConditional.PlayerLearnCampJob = 1
    endif
    if(pr >= 3 && HandlerConditional.PlayerKnowsRandomJob != 1)
        HandlerConditional.PlayerLearnRandomJob = 1
    endif

    akMadame.SetFactionRank(MadameFaction, 0)
    akPlayer.RemoveFromFaction(MadameFaction)
endFunction


; ------------ QUEST KICKERS --------------
Function SimplerJobQuestKicker(Actor Madame)
    ; WS edit - replacing foodjob with simplerjob
    ;FoodJob.Start()
    ;FoodJob.setMadame(Madame)
    SimplerJob.Start()
    SetMadame(Madame, 1)
endFunction


Function SingleJobMonitorKicker(Actor Madame)
    SingleJob.Start()
    SingleJob.SetStage(0)
    SingleJob.ResetVariables()
    SetMadame(Madame, 2)
endFunction

Function SingleJobQuestKicker(Actor Client, bool once = false)    
    SingleJobScript.Start()
    SingleJobScript.SetOnce(once)
    SingleJobScript.ForceSpeakerClient(Client)
endFunction


Function SingleJobQuestKickerAndApproach(Actor Client)
    SingleJobQuestKicker(Client)
endFunction

Function HomeJobQuestKicker(Actor Madame)
    HomeJob = QuestKicker(HomeJobs,lastHomeJob)

    if(HomeJob)
        HomeJob.setMadame(Madame)
        SetMadame(Madame, 3)
    endif
endFunction

Function CampJobQuestKicker(Actor Madame)
    CampJob = QuestKicker(CampJobs,lastCampJob)

    if(CampJob)
        CampJob.setMadame(Madame)
        SetMadame(Madame, 4)
    endif
endFunction

Function RandomJobQuestKicker(Actor Madame)
    currentQuest = QuestKicker(RandomQuests,lastRandomJob)
    
    if(currentQuest)
        currentQuest.setMadame(Madame)
        SetMadame(Madame, 5)
    endif
endFunction


; ------------- QUEST FAILURE --------------

; WS edit - adding functions for SimplerJob
Function SimplerJobQuestFail()
    ResetMadame()
    TriggerFailCD()
    SimplerJob.Stop()
endFunction

; WS edit - adding functions for SimplerJob
Function SimplerJobLeave()
    if(SimplerJob.GetStage() == 20 || SimplerJob.GetStage() == 30); food or gold
        Debug.Notification("You left the inn with the innkeeper's property")
        TriggerFailCD()
    
        ; consequence ??
        int amount = (100.0 * BountyMult) as int
        akMadame.GetCrimeFaction().ModCrimeGold(amount)
        Debug.Notification(amount+"gold bounty added")
        ModBountyMult(1)
    else
        Debug.Notification("You quitted serving food at the inn")
    endif

    ResetMadame()    
    SimplerJob.Stop() 
    SingleJob.Stop()
endFunction

Function SingleJobQuestFail()
    SingleJob.Stop()
endFunction


Function SingleJobLeave()
    if(UndeclaredJobs.GetValue() > 0)
        Debug.Notification("You left town with the innkeeper's gold")
        TriggerFailCD()

        ; consequence ??
        int amount =  (BountyMult * (UndeclaredJobs.GetValueInt() * HandlerConfig.BaseGoldPerClient * HandlerConfig.BaseGoldMadameCut * BountyMult) / 100.0) as int
        akMadame.GetCrimeFaction().ModCrimeGold(amount)
        Debug.Notification(amount+" gold bounty added")
        ModBountyMult(1)
    else
        Debug.Notification("You left the prostitution job behind you")
    endif

    ResetMadame()
    UndeclaredJobs.SetValue(0)
    SingleJob.CompleteAllObjectives()
    SingleJob.StopFollow()
    SingleJob.Stop()
endFunction


Function HomeJobQuestFail()
    HomeJob.FailAllObjectives()
    HomeJob.SetStage(201)     ;to get the quest fail message
    EndHomeJob()              ;this will ensure the homeJob CD is triggered, and that the quest's shutdown stage is called, and also calls ResetMadame()
endFunction


Function CampJobQuestFail()
    CampJob.FailAllObjectives()
    CampJob.SetStage(201)     ;to get the fail message
    endCampJob()
endFunction


Function RandomJobQuestFail()
    ResetMadame()
    TriggerRandomJobCD()
    currentQuest.FailAllObjectives()
    currentQuest.setStage(200)
    currentQuest.Stop()
    currentQuest = None
endFunction

;
; ---------- FOOD JOB REWARD - WS added
;
Function GetSimplerJobReward(bool success = true)
    if(success)
        SimplerJobScript.GetTip()
    endif
    ResetMadame() 
    SimplerJob.Stop()
endFunction

;
; ----------- SINGLE JOB REWARD -------------
;
Function GetSingleJobReward(int lie)
    int amount

    if (lie == 0)
        amount =  Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 100)
        ModBountyMult(UndeclaredJobs.GetValueInt() * (-1))
    elseif (lie == 1) 
        amount =  Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 1000)
    elseif (lie > 1)
        amount = Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 33)
        akMadame.GetCrimeFaction().ModCrimeGold(Math.floor(amount * BountyMult))
        Debug.Notification("The innkeeper put a bounty on my head, I'll have to sort that out with the guards")
        ModBountyMult(1)
        TriggerFailCD()
        amount = 0
    endif
    
    totalReward = 0;

    if(amount != 0)
        int goldCount = Game.GetPlayer().GetItemCount(Gold)
        if(goldCount < amount)
            amount -= goldCount
            MissingMoney.mod(amount)
            UpdateCurrentInstanceGlobal(MissingMoney) 
            amount = goldCount
        endIf
        akMadame.AddItem(Gold, amount)
        akPlayer.RemoveItem(Gold,  amount)
    endif

    ResetMadame()
    UndeclaredJobs.SetValue(0)
    SingleJobMonitor.Stop()
    SingleJob.UnregisterForUpdate()
    SingleJob.Stop()
    
    ;Finish misc quest for learning about prostitution if present
    If IsObjectiveDisplayed(10)
        SetObjectiveCompleted(10)
    EndIf
endFunction


int Function CalcReward(float QM = 1.0, float PERF = 1.0, string Type = "All",int repetitions=1)
    float BG = HandlerConfig.BaseGoldPerClient ; base cost
    float SM = akPlayer.GetAV("Speechcraft") * HandlerConfig.GoldBonusPerSpeechcraft ; speechcraft modifier
    float FM = akPlayer.GetFactionRank(ProstituteFaction) * HandlerConfig.GoldBonusPerRank ; faction reputation modifier
    float GM = 0.0

    if(Game.GetPlayer().GetActorBase().GetSex() == 1)
        GM = HandlerConfig.FemaleGoldBonus
    else
        GM = HandlerConfig.MaleGoldBonus
    endif

    float MOD
    float PM
    if(Type == "Oral" || Type == "Blowjob" || Type == "Cunnilingus")
        MOD = HandlerConfig.OralModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Oral") 
    elseif(Type == "Anal")
        MOD = HandlerConfig.AnalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Anal") 
    elseif(Type == "Vaginal")
        MOD = HandlerConfig.VaginalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Vaginal") 
    elseif(Type == "Rape")
        MOD = HandlerConfig.RapeModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Victim") 
    elseIf(Type == "Lesbian")
        MOD = HandlerConfig.VaginalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Vaginal") 
    else
        MOD = 1.0 ; overall quest modifier
        PM =   HandlerConfig.GoldBonusPerSexRank * (SexLab.GetPlayerStatLevel("Anal") + SexLab.GetPlayerStatLevel("Vaginal") + SexLab.GetPlayerStatLevel("Oral"))/3
    endif

    MOD *= PERF * QM

    int payment = Math.Floor((BG + SM + FM + PM + GM) * MOD)

    if(repetitions > 1)
        int multipleBonus=  Math.Floor(payment * (repetitions - 1) * HandlerConfig.MultipleBonus)
        payment = payment + multipleBonus
    endif

    return     payment
endFunction

;
; ----------- HOME JOB REWARD -------------
;
Function GetHomeJobReward()
    float PERF = HandlerConditional.PerformanceRewardMod
    float QM = 3.0 * HandlerConfig.HomeDeliveryQuestModifier

    akPlayer.AddItem(Gold, CalcReward(QM, PERF))
    HomeJob.CompleteAllObjectives()
    EndHomeJob()
endFunction

Function EndHomeJob()
    HomeJob.Stop()
    ModBountyMult(-2)
    ResetMadame()    
    TriggerHomeJobCD()
endFunction

;
; ----------- CAMP JOB REWARD -------------
;
Function GetCampJobReward()
    float PERF = (CampJob as mf_CampJobQuestScript).GetModifier() ; overall quest modifier
    float QM = 0.75 * HandlerConfig.CampJobQuestModifier

    ModBountyMult(-PERF as int)
    
    akPlayer.AddItem(Gold, CalcReward(QM, PERF))
    CampJob.CompleteAllObjectives()
    endCampJob()
endFunction

Function endCampJob()
    ResetMadame()    
    TriggerCampJobCD()
    CampJob.stop()
endFunction
;
; ----------- RANDOM JOB REWARD -------------
;
Function GetRandomJobReward()
    ModBountyMult(-5)
    ResetMadame()    
    TriggerRandomJobCD()
    currentQuest.Stop()
    currentQuest = None
    HandlerConditional.GrantExtraReward = false;
endFunction

Function GetRandomJobExtraReward()
    ModBountyMult(-5)
    ResetMadame()    
    TriggerRandomJobCD()
    (currentQuest as MF_RandomQuest).getExtraReward()
    currentQuest.Stop()
    currentQuest = None
    HandlerConditional.GrantExtraReward = false;
endFunction

;
; ----------- REWARD FROM CLIENT -------------
;
Function GetRewardSingleFromClient(Actor akClient, int repetitions=0, int jobNumeric = -1)
    float PERF = HandlerConditional.PerformanceRewardMod
    float QM = 1.0

    string jobType= akJobType
    if(jobNumeric == 1)
        jobType= "Oral"
    elseif(jobNumeric == 2)
        jobType= "Vaginal"
    elseif(jobNumeric == 3)
        jobType= "Anal"
    elseif(jobNumeric == 4)
        jobType= "Things"
    elseif(jobNumeric == 5)
        jobType= "Rape"
    elseif(jobNumeric == 7)
        jobType= "Lesbian"
    endIf


    if(repetitions > 0)
        int reward = CalcReward(QM, PERF, jobType,repetitions)
        totalReward += reward
        akPlayer.AddItem(Gold, reward)
        int t = UndeclaredJobs.GetValueInt() + 1
        UndeclaredJobs.SetValue(t)
        UpdateCurrentInstanceGlobal(UndeclaredJobs)
    endif
endFunction

event EvaluateSex(string eventName, string argString, float argNum, form sender)
    CalcRewardMod(argString)
    ; Debug.Notification("Sex lasted " + sexLasted + " sec")
    UnregisterForModEvent("AnimationEnd_GetTime") 
endEvent

Function CalcRewardMod(string argString)
    float sexLasted = SexLab.HookTime(argString)

    if(sexLasted > HandlerConfig.TimeForFullReward)
        HandlerConditional.PerformanceRewardMod = 1.0
    else
         HandlerConditional.PerformanceRewardMod = sexLasted / HandlerConfig.TimeForFullReward
    endif


endFunction


Function IncrementTotalClients(int c)
    int t = TotalClients.GetValueInt()
    TotalClients.SetValue(ValidateStatInt("Client Count", t, c))
    UpdateCurrentInstanceGlobal(TotalClients)
endFunction


Function SetRefractory(Actor Client, bool satisfied=true)
    if(satisfied)
        RefractoryS.Cast(Client, Client)
    else
        RefractoryD.Cast(Client, Client)
    endIf
endFunction


sslThreadController Function PerformSex(Actor akClient, string type, string aggr = "None", string next = "None",bool isPlayerVictim=false, bool foreplay=false, bool switchOnFF =false)

    sslBaseAnimation[] anims

    actor[] actors = new actor[2]
    int playerIndex =0
    actors[0] = akPlayer
    actors[1] = akClient
    
    int sex0 = actors[0].GetActorBase().GetSex()
    int sex1 = actors[1].GetLeveledActorBase().GetSex() 

    int f  = sex0 + sex1
    int m = 2 - f

    string option = ""
    string suppress ="Aggressive"
    if(aggr != "None" || isPlayerVictim)
        option = ",Aggressive"
        suppress =""
    endif

    ; sort the player/client depending on the anim type that will be chosen
    if(f == 2); FF
        option = ""
        suppress ="Aggressive"
        if(type == "Oral" && !switchOnFF)
            actors[0] = akClient
            actors[1] = akPlayer
            playerIndex=1
        elseif(switchOnFF)
            actors[0] = akClient
            actors[1] = akPlayer
            playerIndex=1
        endif
        
        ;ws edit - searching by "FF,<type>" when type=oral removes a lot of valid cunnilingus animations - search for tag cunnilingus instead, with 69 suppress 
        if type == "Oral"
            anims = SexLab.GetAnimationsByTags(2, "Cunnilingus", "69", requireAll=true)
        Else
            ;if type isn't Oral, then use the code that was already here
            anims = SexLab.GetAnimationsByTags(2, "FF,"+ type+ option,suppress, requireAll=true)
        EndIf

        if(anims.Length == 0)
            anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress, requireAll=true)
        endif
    elseif(f == 1);FM || MF
        if(sex0 == 0) ;PC is male
            actors[0] = akPlayer
            actors[1] = akClient
            playerIndex=1
        endif
        anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress+",69", requireAll=true)
    else; MM
        anims = SexLab.GetAnimationsByTags(2, "MM,"+ type+ option,suppress, requireAll=true)
        if(anims.Length == 0)
            anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress, requireAll=true)
        endif
    endif


    if(anims.Length == 0)
        Debug.Notification("You've blacklisted all consensual "+type+" sex anims. This won't work.")
        anims = SexLab.GetAnimationsByTags(2,"Sex")
    endif

    SetRefractory(akClient)

    return fuck(actors,playerIndex,anims,foreplay,next,type,isPlayerVictim).StartThread()
    
endFunction

sslThreadModel Function fuck(Actor[] actors, int playerIndex, sslBaseAnimation[] anims, bool foreplay = true, string next = "None",string type = "None", bool isPlayerVictim = false)

    akJobType = type
    IncrementTotalClients(1)

    bool[] equip0 = New bool[33]
    bool[] equip1 = New bool[33]
    int i=0
    While(i < 33)
        equip0 = false
        equip1 = false
        i += 1
    endWhile

    if(type == "Oral")
        equip0[0] = true ;head
        equip0[3] = true ;hand
        equip0[4] = true ;forearms
        equip0[9] = true ;shield
        equip0[14] = true ;face
        equip0[32] = true ;weapon

        equip1[2] = true ;body
        equip1[9] = true ;shield
        equip1[16] = true ;chest
        equip1[19] = true ;pelvis
        equip1[28] = true ;undergarment
        equip1[32] = true ;weapon    
    else
        equip0[2] = true ;body
        equip0[9] = true ;shield
        equip0[16] = true ;chest
        equip0[19] = true ;pelvis
        equip0[28] = true ;undergarment
        equip0[32] = true ;weapon    

        equip1[2] = true ;body
        equip1[9] = true ;shield
        equip1[16] = true ;chest
        equip1[19] = true ;pelvis
        equip1[28] = true ;undergarment
        equip1[32] = true ;weapon    
    endif

    RegisterForModEvent("AnimationEnd_GetTime", "EvaluateSex")
    While (SexLab.FindActorController(actors[0]) != -1 || SexLab.FindActorController(actors[1]) != -1)
        Utility.Wait(1.0)
    endwhile

    sslThreadModel th = SexLab.NewThread()
    if(actors.length == 2)
        if(playerIndex == 1)
            th.AddActor(actors[0])
            th.AddActor(actors[1], isVictim= isPlayerVictim)
            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[1], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
            endif
        else
            th.AddActor(actors[0], isVictim= isPlayerVictim)
            th.AddActor(actors[1])

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[0], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[1], equip1)
            endif
        endif
    elseif(actors.length == 3)
        if(playerIndex == 0)
            th.AddActor(actors[0], isVictim= isPlayerVictim)
            th.AddActor(actors[1])
            th.AddActor(actors[2])

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[0], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[1], equip1)
                th.SetStrip(actors[2], equip1)
            endif
        elseif(playerIndex == 1)
            th.AddActor(actors[0])
            th.AddActor(actors[1], isVictim= isPlayerVictim)
            th.AddActor(actors[2])
            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[1], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
                th.SetStrip(actors[2], equip1)
            endif
        elseif(playerIndex == 2)
            th.AddActor(actors[0])
            th.AddActor(actors[1])
            th.AddActor(actors[2], isVictim= isPlayerVictim)

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[2], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
                th.SetStrip(actors[1], equip1)
            endif
        endif
    endIf
    th.SetAnimations(anims)
    if(isPlayerVictim)
        th.DisableLeadIn(true) 
    else
        th.DisableLeadIn(!foreplay) 
    endif
    ;Bed Search is Disabled if a CenterObject is set
    ;if(!HandlerConfig.UseBeds)    ;ws - commented out - this might be what's causing issues with the automatic free cam (edit: it was!)
    ;    th.CenterOnObject(actors[playerIndex])
    ;endIf
    ;WS - restoring UseBeds MCM function
    If(!HandlerConfig.UseBeds) 
        th.DisableBedUse(true)
    EndIf
    th.SetHook("GetTime")
    if(next != "None")
        th.SetHook(next)
    endif
    return th

endFunction


sslThreadController Function PerformCreatureSex(Actor[] creatures, string next = "None")
    sslThreadModel th = SexLab.NewThread()
    th.AddActor(akPlayer, isVictim=true)
    int count = 0
    while count < creatures.length
        th.AddActor(creatures[count])
        count= count+1
    endWhile

    if(next != "None")
        th.SetHook(next)
    endif
    th.CenterOnObject(akPlayer)
    return th.StartThread()    
endFunction

sslThreadController Function PerformThreesome(Actor akClient, Actor akGuest, string next = "None", bool isPlayerVictim =false)
     IncrementTotalClients(2)
     SetRefractory(akClient)
     SetRefractory(akGuest)

     sslBaseAnimation[] anims
     actor[] actors = new actor[3]
     int playerIndex =0
     actors[0] = akPlayer
     actors[1] = akClient
     actors[2] = akGuest

     int sex0 = Game.GetPlayer().GetActorBase().GetSex()
     int sex1 = akClient.GetLeveledActorBase().GetSex() 
     int sex2 = akGuest.GetLeveledActorBase().GetSex() 
     
     int c = 1
     sslBaseAnimation[] anims2
     
     int f  = sex0 + sex1 + sex2
     int m = 3 - f

     if(sex0 == 1) ; female PC
        if(sex1 == 1); female NPC
            if(sex2 == 1); FFF
                c = 2
                anims  = SexLab.GetAnimationsByTags(2, "Cunnilingus")
                if(anims.length ==0)
                    anims  = SexLab.GetAnimationsByTag(2, "FF")
                endif
                if(anims.length ==0)
                    anims  = SexLab.GetAnimationsByTag(2, "MF,FM")
                endif
                anims2 = SexLab.GetAnimationsByTags(1, "F", "Masturbation")
            else
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            endif
        else; male NPC
            if(sex2 == 1) ; FMF
                actors[0] = akGuest
                actors[1] = akPlayer
                actors[2] = akClient
                playerIndex =1
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ;FMM
                anims = SexLab.GetAnimationsByTags(3, "MMF")
            endif
        endif
     else; male PC
        if(sex1 == 1)
            if(sex2 == 1); MFF
                actors[0] = akGuest
                actors[2] = akPlayer
                playerIndex =2
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ; MFM
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            endif
        else
            if(sex2 == 1) ; MMF
                actors[1] = akGuest
                actors[2] = akClient
            
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ;MMM
                anims  = SexLab.GetAnimationsByTags(3, "MMF") ;player in female position
            endif
        endif 
     endif
     
     if(anims.Length == 0)
        Debug.Notification("You've blacklisted all threesome sex anims. This won't work.")
        if(c == 1)
            anims = SexLab.GetAnimationsByTags(3,"Sex")
        else
            anims = SexLab.GetAnimationsByTags(2,"Sex")
            anims2 = SexLab.GetAnimationsByTags(1,"Sex")
        endif
     endif
        RegisterForModEvent("AnimationEnd_GetTime", "EvaluateSex")
        While (SexLab.FindActorController(actors[0]) != -1 ||SexLab.FindActorController(actors[1]) != -1 || SexLab.FindActorController(actors[2]) != -1)
            Utility.Wait(1.0)
        endwhile
        if(c == 1)
            sslThreadModel th = SexLab.NewThread()
            if(playerIndex ==0)    
                th.AddActor(actors[0],isVictim = isPlayerVictim)
                th.AddActor(actors[1])
                th.AddActor(actors[2])
            elseif(playerIndex ==1)
                th.AddActor(actors[0])
                th.AddActor(actors[1],isVictim = isPlayerVictim)
                th.AddActor(actors[2])
            else
                th.AddActor(actors[0])
                th.AddActor(actors[1])
                th.AddActor(actors[2],isVictim = isPlayerVictim)
            endif
            th.SetAnimations(anims)
            th.DisableLeadIn(isPlayerVictim) 
            th.SetHook("GetTime")
            if(next != "None")
                th.SetHook(next)
            endif
            return th.StartThread()
        else
            sslThreadModel th2 = SexLab.NewThread()
            th2.AddActor(actors[1])
            th2.SetAnimations(anims2)
            th2.DisableLeadIn(true) 
            th2.StartThread()    
        
            sslThreadModel th1 = SexLab.NewThread()
            if(playerIndex ==0)    
                th1.AddActor(actors[0],isVictim = isPlayerVictim)
                th1.AddActor(actors[2])
            else
                th1.AddActor(actors[0])
                th1.AddActor(actors[2],isVictim = isPlayerVictim)
            endif
            th1.SetAnimations(anims)
            th1.DisableLeadIn(true) 
            th1.SetHook("GetTime")
            if(next != "None")
                th1.SetHook(next)
            endif
            return th1.StartThread()
        endif
endFunction


sslThreadController Function PerformMasturbation(Actor akSoloer, string next = "None")
 int sex = akSoloer.GetLeveledActorBase().GetSex() 
 
 akJobType = "Masturbation"
 sslBaseAnimation[] anims
 if(sex == 0)
    anims = SexLab.GetAnimationsByTag(1, "M", akJobType,  requireAll=true)    
    ;anims = SexLab.GetAnimationsByTag(1, "M", akJobType, tagSuppress="Zaz", requireAll=true)
 else
    anims = SexLab.GetAnimationsByTag(1, "F", akJobType, requireAll=true)
    ;anims = SexLab.GetAnimationsByTag(1, "F", akJobType, tagSuppress="Zaz", requireAll=true)
 endif 
 
 if(anims.Length == 0)
    Debug.Notification("You've blacklisted all consensual "+akJobType+" sex anims. This won't work.")
    return None
 else
      While (SexLab.FindActorController(akSoloer) != -1 )
        Utility.Wait(1.0)
    endwhile
    sslThreadModel th = SexLab.NewThread()
    th.AddActor(akSoloer)
    th.SetAnimations(anims)
    th.DisableLeadIn(true)
    if(next != "None")
        th.SetHook(next)
    endif
    return th.StartThread()
 endif
endFunction

Function PerformDance()

endFunction

Function FadeToBlack()
    akPlayer.SetRestrained(true)    
    FadeOut.Apply()
    Utility.Wait(2.5) ; since Fadeout lasts exactly 3.0s, we need to allow some script delay
    FadeOut.PopTo(BlackScreen)
endFunction

Function FadeFromBlack()
    BlackScreen.PopTo(FadeIn)    
    Utility.Wait(2.0)        
    FadeIn.Remove()        
    akPlayer.SetRestrained(false)
endFunction

MF_RandomQuest Function QuestKicker(FormList quests,int lastIndex)

    Debug.Trace("[Radiant Prostitution] try to start a quest from list " + quests.GetName())
    Debug.Trace("[Radiant Prostitution] last Index was " + lastIndex)

    MF_RandomQuest questToStart = randomQuest(quests, lastIndex)

    Debug.Trace("[Radiant Prostitution] Try to start Quest " + questToStart)

    int try1 = 0
    While(!questToStart.IsRunning() && try1 < 5)
        int try2 = 0
        Debug.Trace("[Radiant Prostitution] Are Preconditions fullfilled ? " + (questToStart.checkConditions()))
        if(questToStart.checkConditions())
            questToStart.Start() 
            Utility.wait(0.5)
            While(!questToStart.IsRunning() && try2 < 5)
                Debug.Trace("[Radiant Prostitution] Quest not started Retry "+ try2)
                questToStart.Start()
                try2 += 1
                Utility.wait(0.5)
            endWhile
        endIf
        if(!questToStart.IsRunning())
            Debug.Trace("[Radiant Prostitution] Quest did not start get a new one")
            questToStart = randomQuest(quests, lastIndex)
            Debug.Trace("[Radiant Prostitution] New Quest is "+ questToStart)
            questToStart.Start() 
            try1 += 1
        endIf
    endWhile

    if(questToStart.IsRunning())
        Debug.Trace("[Radiant Prostitution] Quest started")
        return questToStart
    endif
    
    Debug.Trace("[Radiant Prostitution] no Quest Could be started")
    Debug.Notification("No quest was started. Please try again.")
    return none
endFunction

MF_RandomQuest Function randomQuest(FormList quests, int lastIndex)

    int listSize = quests.GetSize()
    
    if(listSize <= 0)
        ErrorMessage.show()
    endIf

    ; WS - commented out, this method of picking a quest confuses me and seems to cause predictable repetition even after the first round
    ;lastIndex = lastIndex + Utility.RandomInt(1, Math.ceiling(listSize / 2))
    ;while(lastIndex > listSize - 1)
    ;    lastIndex = lastIndex - (listSize - 1)
    ;endWhile
    
    
    ; WS - instead of the above whatever-the-hell-that-is, all we want is ensure that a random quest isn't given twice in a row, if there are more than 2 choices
    ; note: the WHILE needs to check if listSize is larger than one, so we don't get stuck if the list only has 1 quest
    ; and if the listSize is 2, we need to do RandomInt(0,1) instead, otherwise it'll always alternate between one and the other with no randomness
    int newIndex = lastIndex
    if listSize == 2
        newIndex = Utility.RandomInt(0,1)
    Else
        While ( (newIndex == lastIndex) && (listSize > 1) )
            newIndex = Utility.RandomInt(0, (listSize - 1))
        EndWhile
    EndIf

    Debug.Trace("MF_RP TRACE : FINAL INDEX IS " + newIndex + " (" + quests.GetAt(newIndex) + ")")
    MF_RandomQuest questToStart = quests.GetAt(newIndex) as MF_RandomQuest

    if(questToStart.getRank() == 1)
        lastHomeJob = newIndex
    elseif(questToStart.getRank() == 2)
        lastCampJob = newIndex
    elseif(questToStart.getRank() >= 3)
        lastRandomJob = newIndex
    endIf

    return questToStart
endFunction


Function loadFrostfall()
    isFrostfallLoaded = false
    int Mods = Game.GetModCount()
    int i
    While i < Mods
        string Modname = Game.GetModName(i)
        If !isFrostfallLoaded && Modname == "Chesko_Frostfall.esp"
            isFrostfallLoaded = true
            Frostfall_exposurePoints = Game.GetFormFromFile(0x00000183d, "chesko_frostfall.esp") as GlobalVariable
            return
        EndIf
        i += 1
    EndWhile
EndFunction


Function frostfallWarmPlayer()
    if (isFrostfallLoaded)
        Frostfall_exposurePoints.SetValue(120)
    Else
        loadFrostfall()
        If (isFrostfallLoaded)
            Frostfall_exposurePoints.SetValue(120)
        EndIf
    EndIf
EndFunction

 

 

 

Just saw under the hidden tab.....phew over my head?

The reason i mentioned the nexus mod was that its possible that it has to be a "vanilla" male NPC wearing tavern clothes for it to fire positive......what do i know....nothing

Link to comment
23 minutes ago, iggypop1 said:

Just saw under the hidden tab.....phew over my head?

The reason i mentioned the nexus mod was that its possible that it has to be a "vanilla" male NPC wearing tavern clothes for it to fire positive......what do i know....nothing

You may be right on that, the prostitution code needs a elseif added and I am going to look into it later this week

Link to comment

One of my wishes was granted! The home quest is female only! THANK YOU! But I want to make a suggestion.

 

What I believe would be awesome is SLSO. The time needed to have sex for "full reward" is a little outdated IMHO. Would be grand to have the clients say "This was shit! I won't pay you!" etc like SexLab Survival does for Begging.

Also I think there is no check that you are having sex with someone because if you put "Free Roaming Prostitution" to passive or both, clients still come while you are in a scene. Also any SexLab scene can be interrupted by clients. DUDE! I am fucking here wait!

Unless this was fixed?

 

Again THANK so much you for this. The best prostitution mod IMO.

 

Link to comment
18 hours ago, Sorrow_421 said:

One of my wishes was granted! The home quest is female only! THANK YOU! But I want to make a suggestion.

 

What I believe would be awesome is SLSO. The time needed to have sex for "full reward" is a little outdated IMHO. Would be grand to have the clients say "This was shit! I won't pay you!" etc like SexLab Survival does for Begging.

Also I think there is no check that you are having sex with someone because if you put "Free Roaming Prostitution" to passive or both, clients still come while you are in a scene. Also any SexLab scene can be interrupted by clients. DUDE! I am fucking here wait!

Unless this was fixed?

 

Again THANK so much you for this. The best prostitution mod IMO.

 

Thanks, I like the refusal to pay but as far as someone approaching you during a sexlab sexscene, I cannot get another NPC to approach me during a sex scene on my end, never have been able too, have never "fixed it" cause you are the first person to say its ever happen, I just tried to make it happen and it doesnt, its in the script to not happen until you collect your gold

Link to comment

@-Caden-  Hi about the MCM. There is a panic button what do that do? And then there is a NPC/NPC reset quest button. I use this if the NPCs for some reason gets stocked on stairs or slopes  if any NPCs get stucked the mod stops working for other NPCs as well. So i use this button to sort of restart the NPC part of the mod.

My problem is that it wont restart now......hm  do i a have to go sleep in a secluded cell for 72 hours? or what to do exiting the game reloading doesnt help so hmmm??

 

 Edit:Ok did the sleeping and then i could reset NPCs scenes:classic_angel:

Link to comment
On 3/16/2021 at 12:51 PM, -Caden- said:

ok thanks for the info. knowing about the female animation thing might help cause it might help me pin it down in the handler script, this mod has all the sex and rewards in one script


 

  Reveal hidden contents

 

Scriptname mf_Handler extends Quest  

SexLabFramework Property SexLab Auto

mf_Handler_Config Property HandlerConfig Auto
mf_Variables Property HandlerConditional Auto

ImageSpaceModifier Property FadeIn  Auto  
ImageSpaceModifier Property FadeOut  Auto  
ImageSpaceModifier Property BlackScreen  Auto  

Message Property ErrorMessage  Auto 

Armor Property WenchCloths  Auto  
Armor Property WenchBoots  Auto  
MiscObject Property Gold  Auto 
; ------ SERVING FOOD QUEST ------------------
MF_FoodJob Property FoodJob Auto
Quest Property SimplerJob  Auto  
mf_simplerjobscript Property SimplerJobScript  Auto  
float TimeLastJobFailed = 0.0
float TimeLastFailJob = 0.0
; ------ FREE ROAMING PROSTITUTION QUEST -----
Quest Property SingleJobMonitor Auto
mf_SolicitPlayerMainScript Property SingleJobMonitorScript Auto
mf_SimpleJobQuestScript Property SingleJob Auto
mf_SimpleJobQuestScript Property SingleJobScript Auto
String akJobType
int totalReward = 0
; ------ HOME DELIVERY QUEST -----------------
MF_RandomQuest Property HomeJob Auto
FormList Property HomeJobs  Auto  
float TimeLastHomeJobCompleted
; ------ MILITARY CAMP QUEST -----------------
MF_RandomQuest Property CampJob Auto
FormList Property CampJobs  Auto
float TimeLastCampJobCompleted
; ------ RANDOM JOB QUEST --------------------
FormList Property RandomQuests Auto
MF_RandomQuest currentQuest
float TimeLastRandomJobCompleted

GlobalVariable Property UndeclaredJobs Auto
GlobalVariable Property TotalClients  Auto
GlobalVariable Property MissingMoney  Auto  
Faction Property ProstituteFaction Auto
Faction Property MadameFaction  Auto 

SPELL Property RefractoryS Auto
SPELL Property RefractoryD Auto

FormList Property BeastRace Auto
FormList Property ElfRace Auto
FormList Property HumanRace Auto

ReferenceAlias Property akPlayerRef Auto
Actor Property akPlayer Auto
int Property PlayerRace Auto

Actor Property akMadame Auto

float Property BountyMult = 1.0 Auto

int lastHomeJob = 0
int lastCampJob = 0
int lastRandomJob = 0

;Frostfall things
bool isFrostfallLoaded = false
GlobalVariable  property Frostfall_exposurePoints = none  auto

SexLabFramework Function GetSexLab()
    return SexLab
endFunction

Actor Function GetPlayer()
    return akPlayer
endFunction

int Function GetScanInterval()
    return HandlerConfig.ScanInterval as int
endFunction

int Function GetMaxRepetitions()
    return (HandlerConfig.MaxRepetitions + 1) as int   ;WS note - the +1 is because of a mismatch between the MCM descriptions and how the scripts use the MaxRepetitions var. (as far as scripts are concerned, a single sex scene is already 1 repetition)
endFunction

Function AddInitClothes()
    HandlerConditional.GotClothes = true

    int config = JValue.readFromFile("Data/MF_RP_Config.json")

    if(config != 0)
        form chestPiece = JValue.solveForm(config, ".startCloths.chestPiece")
        akPlayer.addItem(chestPiece,1)

        int rest = JValue.solveObj(config, ".startCloths.rest")
        int count  = JArray.count(rest)
        while(count >= 0 )
            count -= 1
            akPlayer.addItem(JArray.getForm(rest,count),1)    
        endWhile
        JValue.release(rest)
        JValue.release(config)
    else
        akPlayer.addItem(WenchCloths,1)
        akPlayer.addItem(WenchBoots,1)
    endIf
endFunction

Function ModBountyMult(int point)
    if(point < 0)
        BountyMult -= HandlerConfig.BountyDownRate * point
    else
        BountyMult += HandlerConfig.BountyUpRate * point
    endif
    
    if(BountyMult < 1.0)
        BountyMult = 1.0
    elseif(BountyMult > HandlerConfig.MaxBountyMult)
        BountyMult = HandlerConfig.MaxBountyMult
    endif
endFunction


int Function ValidateStatInt(string statName, int localValue, int modLocValue)
    if(SexLab.FindStat(statName) == -1)
        int value = localValue + modLocValue
        SexLab.RegisterStat(statName, value as string) 
        return value
    else
        return SexLab.AdjustBy(statName, modLocValue)
    endif
endFunction


Function TriggerFailCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastFailJob = Utility.GetCurrentGameTime()
    HandlerConditional.FailJobOnCD = 1
endFunction


Function TriggerHomeJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastHomeJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.HomeJobOnCD = 1
endFunction


Function TriggerCampJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastCampJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.CampJobOnCD = 1
endFunction


Function TriggerRandomJobCD()
    RegisterForUpdateGameTime(0.5)
    TimeLastRandomJobCompleted = Utility.GetCurrentGameTime()
    HandlerConditional.RandomJobOnCD = 1
endFunction


Function ResetAllCD()
    HandlerConditional.FailJobOnCD = 0
    HandlerConditional.HomeJobOnCD = 0
    HandlerConditional.CampJobOnCD = 0
    HandlerConditional.RandomJobOnCD = 0
    UnregisterForUpdateGameTime()
endFunction


Event OnUpdateGameTime()
    float time = Utility.GetCurrentGameTime()

    if(TimeLastFailJob +  HandlerConfig.FailJobCD <= time)
    HandlerConditional.FailJobOnCD = 0
    endif
    if(TimeLastHomeJobCompleted + HandlerConfig.HomeJobCD <= time)
    HandlerConditional.HomeJobOnCD = 0
    endif
    if(TimeLastCampJobCompleted + HandlerConfig.CampJobCD <= time)
    HandlerConditional.CampJobOnCD = 0
    endif
    if(TimeLastRandomJobCompleted + HandlerConfig.RandomJobCD <= time)
    HandlerConditional.RandomJobOnCD = 0
    endif

    ;if all of them are off CD, stop receiving events
    if(HandlerConditional.FailJobOnCD == 0 && HandlerConditional.HomeJobOnCD == 0 && HandlerConditional.CampJobOnCD == 0 && HandlerConditional.RandomJobOnCD == 0)
    UnregisterForUpdateGameTime()
    endif
endEvent


Function SetMadame(Actor Madame, int rank)
    akPlayer = akPlayerRef.GetRef() as Actor
    Race pRace = akPlayer.GetActorBase().GetRace()
    if(HumanRace.HasForm(pRace))
        PlayerRace = 1
    elseif(ElfRace.HasForm(pRace))
        PlayerRace = 2
    elseif(BeastRace.HasForm(pRace))    
        PlayerRace = 4
    else
        PlayerRace = 8
    endif

    akMadame = Madame
    akMadame.SetFactionRank(MadameFaction, rank)
    akPlayer.SetFactionRank(MadameFaction, 0) ; just put the player in madame_faction such that we know by looking at ourselves that we are running a quest for a madame

    UndeclaredJobs.SetValue(0)
    ; ...
endFunction


Function Reset()
    akPlayer = akPlayerRef.GetRef() as Actor
    akPlayer.RemoveFromFaction(MadameFaction)
    if(akMadame != None)
     akMadame.SetFactionRank(MadameFaction, 0)
    endif
    ; WS edit - replacing foodjob with simplerjob
    ;FoodJob.Stop()
    SimplerJob.Stop()

    SingleJob.Stop()

    if(HomeJob)
        HomeJob.Stop()
    endif

    if(CampJob)
        CampJob.Stop()
    endif

    if(currentQuest)
        currentQuest.Stop()
    endif
    
    ResetAllCD()
endFunction


Function ResetMadame()
    int tc = TotalClients.GetValueInt()
    if(tc < HandlerConfig.ProstituteRank1)
        akPlayer.SetFactionRank(ProstituteFaction, 0)
    elseif(tc <  HandlerConfig.ProstituteRank2)
        akPlayer.SetFactionRank(ProstituteFaction, 1)
    elseif(tc <  HandlerConfig.ProstituteRank3)
        akPlayer.SetFactionRank(ProstituteFaction, 2)
    elseif(tc <  HandlerConfig.ProstituteRank4)
        akPlayer.SetFactionRank(ProstituteFaction, 3)
    elseif(tc <  HandlerConfig.ProstituteRank5)
        akPlayer.SetFactionRank(ProstituteFaction, 4)
    else
        akPlayer.SetFactionRank(ProstituteFaction, 5)
    endif

    int pr = akPlayer.GetFactionRank(ProstituteFaction)
    if(pr >= 1 && HandlerConditional.PlayerKnowsHomeJob != 1)
        HandlerConditional.PlayerLearnHomeJob = 1
    endif
    if(pr >= 2 && HandlerConditional.PlayerKnowsCampJob != 1)
        HandlerConditional.PlayerLearnCampJob = 1
    endif
    if(pr >= 3 && HandlerConditional.PlayerKnowsRandomJob != 1)
        HandlerConditional.PlayerLearnRandomJob = 1
    endif

    akMadame.SetFactionRank(MadameFaction, 0)
    akPlayer.RemoveFromFaction(MadameFaction)
endFunction


; ------------ QUEST KICKERS --------------
Function SimplerJobQuestKicker(Actor Madame)
    ; WS edit - replacing foodjob with simplerjob
    ;FoodJob.Start()
    ;FoodJob.setMadame(Madame)
    SimplerJob.Start()
    SetMadame(Madame, 1)
endFunction


Function SingleJobMonitorKicker(Actor Madame)
    SingleJob.Start()
    SingleJob.SetStage(0)
    SingleJob.ResetVariables()
    SetMadame(Madame, 2)
endFunction

Function SingleJobQuestKicker(Actor Client, bool once = false)    
    SingleJobScript.Start()
    SingleJobScript.SetOnce(once)
    SingleJobScript.ForceSpeakerClient(Client)
endFunction


Function SingleJobQuestKickerAndApproach(Actor Client)
    SingleJobQuestKicker(Client)
endFunction

Function HomeJobQuestKicker(Actor Madame)
    HomeJob = QuestKicker(HomeJobs,lastHomeJob)

    if(HomeJob)
        HomeJob.setMadame(Madame)
        SetMadame(Madame, 3)
    endif
endFunction

Function CampJobQuestKicker(Actor Madame)
    CampJob = QuestKicker(CampJobs,lastCampJob)

    if(CampJob)
        CampJob.setMadame(Madame)
        SetMadame(Madame, 4)
    endif
endFunction

Function RandomJobQuestKicker(Actor Madame)
    currentQuest = QuestKicker(RandomQuests,lastRandomJob)
    
    if(currentQuest)
        currentQuest.setMadame(Madame)
        SetMadame(Madame, 5)
    endif
endFunction


; ------------- QUEST FAILURE --------------

; WS edit - adding functions for SimplerJob
Function SimplerJobQuestFail()
    ResetMadame()
    TriggerFailCD()
    SimplerJob.Stop()
endFunction

; WS edit - adding functions for SimplerJob
Function SimplerJobLeave()
    if(SimplerJob.GetStage() == 20 || SimplerJob.GetStage() == 30); food or gold
        Debug.Notification("You left the inn with the innkeeper's property")
        TriggerFailCD()
    
        ; consequence ??
        int amount = (100.0 * BountyMult) as int
        akMadame.GetCrimeFaction().ModCrimeGold(amount)
        Debug.Notification(amount+"gold bounty added")
        ModBountyMult(1)
    else
        Debug.Notification("You quitted serving food at the inn")
    endif

    ResetMadame()    
    SimplerJob.Stop() 
    SingleJob.Stop()
endFunction

Function SingleJobQuestFail()
    SingleJob.Stop()
endFunction


Function SingleJobLeave()
    if(UndeclaredJobs.GetValue() > 0)
        Debug.Notification("You left town with the innkeeper's gold")
        TriggerFailCD()

        ; consequence ??
        int amount =  (BountyMult * (UndeclaredJobs.GetValueInt() * HandlerConfig.BaseGoldPerClient * HandlerConfig.BaseGoldMadameCut * BountyMult) / 100.0) as int
        akMadame.GetCrimeFaction().ModCrimeGold(amount)
        Debug.Notification(amount+" gold bounty added")
        ModBountyMult(1)
    else
        Debug.Notification("You left the prostitution job behind you")
    endif

    ResetMadame()
    UndeclaredJobs.SetValue(0)
    SingleJob.CompleteAllObjectives()
    SingleJob.StopFollow()
    SingleJob.Stop()
endFunction


Function HomeJobQuestFail()
    HomeJob.FailAllObjectives()
    HomeJob.SetStage(201)     ;to get the quest fail message
    EndHomeJob()              ;this will ensure the homeJob CD is triggered, and that the quest's shutdown stage is called, and also calls ResetMadame()
endFunction


Function CampJobQuestFail()
    CampJob.FailAllObjectives()
    CampJob.SetStage(201)     ;to get the fail message
    endCampJob()
endFunction


Function RandomJobQuestFail()
    ResetMadame()
    TriggerRandomJobCD()
    currentQuest.FailAllObjectives()
    currentQuest.setStage(200)
    currentQuest.Stop()
    currentQuest = None
endFunction

;
; ---------- FOOD JOB REWARD - WS added
;
Function GetSimplerJobReward(bool success = true)
    if(success)
        SimplerJobScript.GetTip()
    endif
    ResetMadame() 
    SimplerJob.Stop()
endFunction

;
; ----------- SINGLE JOB REWARD -------------
;
Function GetSingleJobReward(int lie)
    int amount

    if (lie == 0)
        amount =  Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 100)
        ModBountyMult(UndeclaredJobs.GetValueInt() * (-1))
    elseif (lie == 1) 
        amount =  Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 1000)
    elseif (lie > 1)
        amount = Math.Floor(totalReward * HandlerConfig.BaseGoldMadameCut / 33)
        akMadame.GetCrimeFaction().ModCrimeGold(Math.floor(amount * BountyMult))
        Debug.Notification("The innkeeper put a bounty on my head, I'll have to sort that out with the guards")
        ModBountyMult(1)
        TriggerFailCD()
        amount = 0
    endif
    
    totalReward = 0;

    if(amount != 0)
        int goldCount = Game.GetPlayer().GetItemCount(Gold)
        if(goldCount < amount)
            amount -= goldCount
            MissingMoney.mod(amount)
            UpdateCurrentInstanceGlobal(MissingMoney) 
            amount = goldCount
        endIf
        akMadame.AddItem(Gold, amount)
        akPlayer.RemoveItem(Gold,  amount)
    endif

    ResetMadame()
    UndeclaredJobs.SetValue(0)
    SingleJobMonitor.Stop()
    SingleJob.UnregisterForUpdate()
    SingleJob.Stop()
    
    ;Finish misc quest for learning about prostitution if present
    If IsObjectiveDisplayed(10)
        SetObjectiveCompleted(10)
    EndIf
endFunction


int Function CalcReward(float QM = 1.0, float PERF = 1.0, string Type = "All",int repetitions=1)
    float BG = HandlerConfig.BaseGoldPerClient ; base cost
    float SM = akPlayer.GetAV("Speechcraft") * HandlerConfig.GoldBonusPerSpeechcraft ; speechcraft modifier
    float FM = akPlayer.GetFactionRank(ProstituteFaction) * HandlerConfig.GoldBonusPerRank ; faction reputation modifier
    float GM = 0.0

    if(Game.GetPlayer().GetActorBase().GetSex() == 1)
        GM = HandlerConfig.FemaleGoldBonus
    else
        GM = HandlerConfig.MaleGoldBonus
    endif

    float MOD
    float PM
    if(Type == "Oral" || Type == "Blowjob" || Type == "Cunnilingus")
        MOD = HandlerConfig.OralModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Oral") 
    elseif(Type == "Anal")
        MOD = HandlerConfig.AnalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Anal") 
    elseif(Type == "Vaginal")
        MOD = HandlerConfig.VaginalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Vaginal") 
    elseif(Type == "Rape")
        MOD = HandlerConfig.RapeModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Victim") 
    elseIf(Type == "Lesbian")
        MOD = HandlerConfig.VaginalModifier
        PM =  HandlerConfig.GoldBonusPerSexRank * SexLab.GetPlayerStatLevel("Vaginal") 
    else
        MOD = 1.0 ; overall quest modifier
        PM =   HandlerConfig.GoldBonusPerSexRank * (SexLab.GetPlayerStatLevel("Anal") + SexLab.GetPlayerStatLevel("Vaginal") + SexLab.GetPlayerStatLevel("Oral"))/3
    endif

    MOD *= PERF * QM

    int payment = Math.Floor((BG + SM + FM + PM + GM) * MOD)

    if(repetitions > 1)
        int multipleBonus=  Math.Floor(payment * (repetitions - 1) * HandlerConfig.MultipleBonus)
        payment = payment + multipleBonus
    endif

    return     payment
endFunction

;
; ----------- HOME JOB REWARD -------------
;
Function GetHomeJobReward()
    float PERF = HandlerConditional.PerformanceRewardMod
    float QM = 3.0 * HandlerConfig.HomeDeliveryQuestModifier

    akPlayer.AddItem(Gold, CalcReward(QM, PERF))
    HomeJob.CompleteAllObjectives()
    EndHomeJob()
endFunction

Function EndHomeJob()
    HomeJob.Stop()
    ModBountyMult(-2)
    ResetMadame()    
    TriggerHomeJobCD()
endFunction

;
; ----------- CAMP JOB REWARD -------------
;
Function GetCampJobReward()
    float PERF = (CampJob as mf_CampJobQuestScript).GetModifier() ; overall quest modifier
    float QM = 0.75 * HandlerConfig.CampJobQuestModifier

    ModBountyMult(-PERF as int)
    
    akPlayer.AddItem(Gold, CalcReward(QM, PERF))
    CampJob.CompleteAllObjectives()
    endCampJob()
endFunction

Function endCampJob()
    ResetMadame()    
    TriggerCampJobCD()
    CampJob.stop()
endFunction
;
; ----------- RANDOM JOB REWARD -------------
;
Function GetRandomJobReward()
    ModBountyMult(-5)
    ResetMadame()    
    TriggerRandomJobCD()
    currentQuest.Stop()
    currentQuest = None
    HandlerConditional.GrantExtraReward = false;
endFunction

Function GetRandomJobExtraReward()
    ModBountyMult(-5)
    ResetMadame()    
    TriggerRandomJobCD()
    (currentQuest as MF_RandomQuest).getExtraReward()
    currentQuest.Stop()
    currentQuest = None
    HandlerConditional.GrantExtraReward = false;
endFunction

;
; ----------- REWARD FROM CLIENT -------------
;
Function GetRewardSingleFromClient(Actor akClient, int repetitions=0, int jobNumeric = -1)
    float PERF = HandlerConditional.PerformanceRewardMod
    float QM = 1.0

    string jobType= akJobType
    if(jobNumeric == 1)
        jobType= "Oral"
    elseif(jobNumeric == 2)
        jobType= "Vaginal"
    elseif(jobNumeric == 3)
        jobType= "Anal"
    elseif(jobNumeric == 4)
        jobType= "Things"
    elseif(jobNumeric == 5)
        jobType= "Rape"
    elseif(jobNumeric == 7)
        jobType= "Lesbian"
    endIf


    if(repetitions > 0)
        int reward = CalcReward(QM, PERF, jobType,repetitions)
        totalReward += reward
        akPlayer.AddItem(Gold, reward)
        int t = UndeclaredJobs.GetValueInt() + 1
        UndeclaredJobs.SetValue(t)
        UpdateCurrentInstanceGlobal(UndeclaredJobs)
    endif
endFunction

event EvaluateSex(string eventName, string argString, float argNum, form sender)
    CalcRewardMod(argString)
    ; Debug.Notification("Sex lasted " + sexLasted + " sec")
    UnregisterForModEvent("AnimationEnd_GetTime") 
endEvent

Function CalcRewardMod(string argString)
    float sexLasted = SexLab.HookTime(argString)

    if(sexLasted > HandlerConfig.TimeForFullReward)
        HandlerConditional.PerformanceRewardMod = 1.0
    else
         HandlerConditional.PerformanceRewardMod = sexLasted / HandlerConfig.TimeForFullReward
    endif


endFunction


Function IncrementTotalClients(int c)
    int t = TotalClients.GetValueInt()
    TotalClients.SetValue(ValidateStatInt("Client Count", t, c))
    UpdateCurrentInstanceGlobal(TotalClients)
endFunction


Function SetRefractory(Actor Client, bool satisfied=true)
    if(satisfied)
        RefractoryS.Cast(Client, Client)
    else
        RefractoryD.Cast(Client, Client)
    endIf
endFunction


sslThreadController Function PerformSex(Actor akClient, string type, string aggr = "None", string next = "None",bool isPlayerVictim=false, bool foreplay=false, bool switchOnFF =false)

    sslBaseAnimation[] anims

    actor[] actors = new actor[2]
    int playerIndex =0
    actors[0] = akPlayer
    actors[1] = akClient
    
    int sex0 = actors[0].GetActorBase().GetSex()
    int sex1 = actors[1].GetLeveledActorBase().GetSex() 

    int f  = sex0 + sex1
    int m = 2 - f

    string option = ""
    string suppress ="Aggressive"
    if(aggr != "None" || isPlayerVictim)
        option = ",Aggressive"
        suppress =""
    endif

    ; sort the player/client depending on the anim type that will be chosen
    if(f == 2); FF
        option = ""
        suppress ="Aggressive"
        if(type == "Oral" && !switchOnFF)
            actors[0] = akClient
            actors[1] = akPlayer
            playerIndex=1
        elseif(switchOnFF)
            actors[0] = akClient
            actors[1] = akPlayer
            playerIndex=1
        endif
        
        ;ws edit - searching by "FF,<type>" when type=oral removes a lot of valid cunnilingus animations - search for tag cunnilingus instead, with 69 suppress 
        if type == "Oral"
            anims = SexLab.GetAnimationsByTags(2, "Cunnilingus", "69", requireAll=true)
        Else
            ;if type isn't Oral, then use the code that was already here
            anims = SexLab.GetAnimationsByTags(2, "FF,"+ type+ option,suppress, requireAll=true)
        EndIf

        if(anims.Length == 0)
            anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress, requireAll=true)
        endif
    elseif(f == 1);FM || MF
        if(sex0 == 0) ;PC is male
            actors[0] = akPlayer
            actors[1] = akClient
            playerIndex=1
        endif
        anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress+",69", requireAll=true)
    else; MM
        anims = SexLab.GetAnimationsByTags(2, "MM,"+ type+ option,suppress, requireAll=true)
        if(anims.Length == 0)
            anims = SexLab.GetAnimationsByTags(2, "MF,"+ type+ option,suppress, requireAll=true)
        endif
    endif


    if(anims.Length == 0)
        Debug.Notification("You've blacklisted all consensual "+type+" sex anims. This won't work.")
        anims = SexLab.GetAnimationsByTags(2,"Sex")
    endif

    SetRefractory(akClient)

    return fuck(actors,playerIndex,anims,foreplay,next,type,isPlayerVictim).StartThread()
    
endFunction

sslThreadModel Function fuck(Actor[] actors, int playerIndex, sslBaseAnimation[] anims, bool foreplay = true, string next = "None",string type = "None", bool isPlayerVictim = false)

    akJobType = type
    IncrementTotalClients(1)

    bool[] equip0 = New bool[33]
    bool[] equip1 = New bool[33]
    int i=0
    While(i < 33)
        equip0 = false
        equip1 = false
        i += 1
    endWhile

    if(type == "Oral")
        equip0[0] = true ;head
        equip0[3] = true ;hand
        equip0[4] = true ;forearms
        equip0[9] = true ;shield
        equip0[14] = true ;face
        equip0[32] = true ;weapon

        equip1[2] = true ;body
        equip1[9] = true ;shield
        equip1[16] = true ;chest
        equip1[19] = true ;pelvis
        equip1[28] = true ;undergarment
        equip1[32] = true ;weapon    
    else
        equip0[2] = true ;body
        equip0[9] = true ;shield
        equip0[16] = true ;chest
        equip0[19] = true ;pelvis
        equip0[28] = true ;undergarment
        equip0[32] = true ;weapon    

        equip1[2] = true ;body
        equip1[9] = true ;shield
        equip1[16] = true ;chest
        equip1[19] = true ;pelvis
        equip1[28] = true ;undergarment
        equip1[32] = true ;weapon    
    endif

    RegisterForModEvent("AnimationEnd_GetTime", "EvaluateSex")
    While (SexLab.FindActorController(actors[0]) != -1 || SexLab.FindActorController(actors[1]) != -1)
        Utility.Wait(1.0)
    endwhile

    sslThreadModel th = SexLab.NewThread()
    if(actors.length == 2)
        if(playerIndex == 1)
            th.AddActor(actors[0])
            th.AddActor(actors[1], isVictim= isPlayerVictim)
            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[1], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
            endif
        else
            th.AddActor(actors[0], isVictim= isPlayerVictim)
            th.AddActor(actors[1])

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[0], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[1], equip1)
            endif
        endif
    elseif(actors.length == 3)
        if(playerIndex == 0)
            th.AddActor(actors[0], isVictim= isPlayerVictim)
            th.AddActor(actors[1])
            th.AddActor(actors[2])

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[0], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[1], equip1)
                th.SetStrip(actors[2], equip1)
            endif
        elseif(playerIndex == 1)
            th.AddActor(actors[0])
            th.AddActor(actors[1], isVictim= isPlayerVictim)
            th.AddActor(actors[2])
            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[1], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
                th.SetStrip(actors[2], equip1)
            endif
        elseif(playerIndex == 2)
            th.AddActor(actors[0])
            th.AddActor(actors[1])
            th.AddActor(actors[2], isVictim= isPlayerVictim)

            if(HandlerConfig.PlayerMinimalStripping)
                th.SetStrip(actors[2], equip0)
            endif
            if(HandlerConfig.ClientMinimalStripping)
                th.SetStrip(actors[0], equip1)
                th.SetStrip(actors[1], equip1)
            endif
        endif
    endIf
    th.SetAnimations(anims)
    if(isPlayerVictim)
        th.DisableLeadIn(true) 
    else
        th.DisableLeadIn(!foreplay) 
    endif
    ;Bed Search is Disabled if a CenterObject is set
    ;if(!HandlerConfig.UseBeds)    ;ws - commented out - this might be what's causing issues with the automatic free cam (edit: it was!)
    ;    th.CenterOnObject(actors[playerIndex])
    ;endIf
    ;WS - restoring UseBeds MCM function
    If(!HandlerConfig.UseBeds) 
        th.DisableBedUse(true)
    EndIf
    th.SetHook("GetTime")
    if(next != "None")
        th.SetHook(next)
    endif
    return th

endFunction


sslThreadController Function PerformCreatureSex(Actor[] creatures, string next = "None")
    sslThreadModel th = SexLab.NewThread()
    th.AddActor(akPlayer, isVictim=true)
    int count = 0
    while count < creatures.length
        th.AddActor(creatures[count])
        count= count+1
    endWhile

    if(next != "None")
        th.SetHook(next)
    endif
    th.CenterOnObject(akPlayer)
    return th.StartThread()    
endFunction

sslThreadController Function PerformThreesome(Actor akClient, Actor akGuest, string next = "None", bool isPlayerVictim =false)
     IncrementTotalClients(2)
     SetRefractory(akClient)
     SetRefractory(akGuest)

     sslBaseAnimation[] anims
     actor[] actors = new actor[3]
     int playerIndex =0
     actors[0] = akPlayer
     actors[1] = akClient
     actors[2] = akGuest

     int sex0 = Game.GetPlayer().GetActorBase().GetSex()
     int sex1 = akClient.GetLeveledActorBase().GetSex() 
     int sex2 = akGuest.GetLeveledActorBase().GetSex() 
     
     int c = 1
     sslBaseAnimation[] anims2
     
     int f  = sex0 + sex1 + sex2
     int m = 3 - f

     if(sex0 == 1) ; female PC
        if(sex1 == 1); female NPC
            if(sex2 == 1); FFF
                c = 2
                anims  = SexLab.GetAnimationsByTags(2, "Cunnilingus")
                if(anims.length ==0)
                    anims  = SexLab.GetAnimationsByTag(2, "FF")
                endif
                if(anims.length ==0)
                    anims  = SexLab.GetAnimationsByTag(2, "MF,FM")
                endif
                anims2 = SexLab.GetAnimationsByTags(1, "F", "Masturbation")
            else
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            endif
        else; male NPC
            if(sex2 == 1) ; FMF
                actors[0] = akGuest
                actors[1] = akPlayer
                actors[2] = akClient
                playerIndex =1
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ;FMM
                anims = SexLab.GetAnimationsByTags(3, "MMF")
            endif
        endif
     else; male PC
        if(sex1 == 1)
            if(sex2 == 1); MFF
                actors[0] = akGuest
                actors[2] = akPlayer
                playerIndex =2
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ; MFM
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            endif
        else
            if(sex2 == 1) ; MMF
                actors[1] = akGuest
                actors[2] = akClient
            
                anims = SexLab.GetAnimationsByTags(3, "MFF")
            else ;MMM
                anims  = SexLab.GetAnimationsByTags(3, "MMF") ;player in female position
            endif
        endif 
     endif
     
     if(anims.Length == 0)
        Debug.Notification("You've blacklisted all threesome sex anims. This won't work.")
        if(c == 1)
            anims = SexLab.GetAnimationsByTags(3,"Sex")
        else
            anims = SexLab.GetAnimationsByTags(2,"Sex")
            anims2 = SexLab.GetAnimationsByTags(1,"Sex")
        endif
     endif
        RegisterForModEvent("AnimationEnd_GetTime", "EvaluateSex")
        While (SexLab.FindActorController(actors[0]) != -1 ||SexLab.FindActorController(actors[1]) != -1 || SexLab.FindActorController(actors[2]) != -1)
            Utility.Wait(1.0)
        endwhile
        if(c == 1)
            sslThreadModel th = SexLab.NewThread()
            if(playerIndex ==0)    
                th.AddActor(actors[0],isVictim = isPlayerVictim)
                th.AddActor(actors[1])
                th.AddActor(actors[2])
            elseif(playerIndex ==1)
                th.AddActor(actors[0])
                th.AddActor(actors[1],isVictim = isPlayerVictim)
                th.AddActor(actors[2])
            else
                th.AddActor(actors[0])
                th.AddActor(actors[1])
                th.AddActor(actors[2],isVictim = isPlayerVictim)
            endif
            th.SetAnimations(anims)
            th.DisableLeadIn(isPlayerVictim) 
            th.SetHook("GetTime")
            if(next != "None")
                th.SetHook(next)
            endif
            return th.StartThread()
        else
            sslThreadModel th2 = SexLab.NewThread()
            th2.AddActor(actors[1])
            th2.SetAnimations(anims2)
            th2.DisableLeadIn(true) 
            th2.StartThread()    
        
            sslThreadModel th1 = SexLab.NewThread()
            if(playerIndex ==0)    
                th1.AddActor(actors[0],isVictim = isPlayerVictim)
                th1.AddActor(actors[2])
            else
                th1.AddActor(actors[0])
                th1.AddActor(actors[2],isVictim = isPlayerVictim)
            endif
            th1.SetAnimations(anims)
            th1.DisableLeadIn(true) 
            th1.SetHook("GetTime")
            if(next != "None")
                th1.SetHook(next)
            endif
            return th1.StartThread()
        endif
endFunction


sslThreadController Function PerformMasturbation(Actor akSoloer, string next = "None")
 int sex = akSoloer.GetLeveledActorBase().GetSex() 
 
 akJobType = "Masturbation"
 sslBaseAnimation[] anims
 if(sex == 0)
    anims = SexLab.GetAnimationsByTag(1, "M", akJobType,  requireAll=true)    
    ;anims = SexLab.GetAnimationsByTag(1, "M", akJobType, tagSuppress="Zaz", requireAll=true)
 else
    anims = SexLab.GetAnimationsByTag(1, "F", akJobType, requireAll=true)
    ;anims = SexLab.GetAnimationsByTag(1, "F", akJobType, tagSuppress="Zaz", requireAll=true)
 endif 
 
 if(anims.Length == 0)
    Debug.Notification("You've blacklisted all consensual "+akJobType+" sex anims. This won't work.")
    return None
 else
      While (SexLab.FindActorController(akSoloer) != -1 )
        Utility.Wait(1.0)
    endwhile
    sslThreadModel th = SexLab.NewThread()
    th.AddActor(akSoloer)
    th.SetAnimations(anims)
    th.DisableLeadIn(true)
    if(next != "None")
        th.SetHook(next)
    endif
    return th.StartThread()
 endif
endFunction

Function PerformDance()

endFunction

Function FadeToBlack()
    akPlayer.SetRestrained(true)    
    FadeOut.Apply()
    Utility.Wait(2.5) ; since Fadeout lasts exactly 3.0s, we need to allow some script delay
    FadeOut.PopTo(BlackScreen)
endFunction

Function FadeFromBlack()
    BlackScreen.PopTo(FadeIn)    
    Utility.Wait(2.0)        
    FadeIn.Remove()        
    akPlayer.SetRestrained(false)
endFunction

MF_RandomQuest Function QuestKicker(FormList quests,int lastIndex)

    Debug.Trace("[Radiant Prostitution] try to start a quest from list " + quests.GetName())
    Debug.Trace("[Radiant Prostitution] last Index was " + lastIndex)

    MF_RandomQuest questToStart = randomQuest(quests, lastIndex)

    Debug.Trace("[Radiant Prostitution] Try to start Quest " + questToStart)

    int try1 = 0
    While(!questToStart.IsRunning() && try1 < 5)
        int try2 = 0
        Debug.Trace("[Radiant Prostitution] Are Preconditions fullfilled ? " + (questToStart.checkConditions()))
        if(questToStart.checkConditions())
            questToStart.Start() 
            Utility.wait(0.5)
            While(!questToStart.IsRunning() && try2 < 5)
                Debug.Trace("[Radiant Prostitution] Quest not started Retry "+ try2)
                questToStart.Start()
                try2 += 1
                Utility.wait(0.5)
            endWhile
        endIf
        if(!questToStart.IsRunning())
            Debug.Trace("[Radiant Prostitution] Quest did not start get a new one")
            questToStart = randomQuest(quests, lastIndex)
            Debug.Trace("[Radiant Prostitution] New Quest is "+ questToStart)
            questToStart.Start() 
            try1 += 1
        endIf
    endWhile

    if(questToStart.IsRunning())
        Debug.Trace("[Radiant Prostitution] Quest started")
        return questToStart
    endif
    
    Debug.Trace("[Radiant Prostitution] no Quest Could be started")
    Debug.Notification("No quest was started. Please try again.")
    return none
endFunction

MF_RandomQuest Function randomQuest(FormList quests, int lastIndex)

    int listSize = quests.GetSize()
    
    if(listSize <= 0)
        ErrorMessage.show()
    endIf

    ; WS - commented out, this method of picking a quest confuses me and seems to cause predictable repetition even after the first round
    ;lastIndex = lastIndex + Utility.RandomInt(1, Math.ceiling(listSize / 2))
    ;while(lastIndex > listSize - 1)
    ;    lastIndex = lastIndex - (listSize - 1)
    ;endWhile
    
    
    ; WS - instead of the above whatever-the-hell-that-is, all we want is ensure that a random quest isn't given twice in a row, if there are more than 2 choices
    ; note: the WHILE needs to check if listSize is larger than one, so we don't get stuck if the list only has 1 quest
    ; and if the listSize is 2, we need to do RandomInt(0,1) instead, otherwise it'll always alternate between one and the other with no randomness
    int newIndex = lastIndex
    if listSize == 2
        newIndex = Utility.RandomInt(0,1)
    Else
        While ( (newIndex == lastIndex) && (listSize > 1) )
            newIndex = Utility.RandomInt(0, (listSize - 1))
        EndWhile
    EndIf

    Debug.Trace("MF_RP TRACE : FINAL INDEX IS " + newIndex + " (" + quests.GetAt(newIndex) + ")")
    MF_RandomQuest questToStart = quests.GetAt(newIndex) as MF_RandomQuest

    if(questToStart.getRank() == 1)
        lastHomeJob = newIndex
    elseif(questToStart.getRank() == 2)
        lastCampJob = newIndex
    elseif(questToStart.getRank() >= 3)
        lastRandomJob = newIndex
    endIf

    return questToStart
endFunction


Function loadFrostfall()
    isFrostfallLoaded = false
    int Mods = Game.GetModCount()
    int i
    While i < Mods
        string Modname = Game.GetModName(i)
        If !isFrostfallLoaded && Modname == "Chesko_Frostfall.esp"
            isFrostfallLoaded = true
            Frostfall_exposurePoints = Game.GetFormFromFile(0x00000183d, "chesko_frostfall.esp") as GlobalVariable
            return
        EndIf
        i += 1
    EndWhile
EndFunction


Function frostfallWarmPlayer()
    if (isFrostfallLoaded)
        Frostfall_exposurePoints.SetValue(120)
    Else
        loadFrostfall()
        If (isFrostfallLoaded)
            Frostfall_exposurePoints.SetValue(120)
        EndIf
    EndIf
EndFunction

 

 

 

Tested again my female PC versus Brenuin in tavern clothes and he was using male animation.....so hm

Link to comment

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

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use