Jump to content

Recommended Posts

Posted

 

 

Since the 1.3 version I have serious problem with the Scent of Sex. It doesn't seem to take sexuality into account at all. It doesn't matter if I choose the sexlab or ck sexuality in the preferences. Sex in rules is defined properly (for example target is human female and source is human male but still most of the time rule causes two females or two males to have sex).

 

I have tried to perform the actor cleanup from the debug menu several times, but no effect.

 

Also the faction/race refresh takes soooo much time...

 

1.2 worked perfectly.

:(

 

You're sure that the 'I play as' setting in Main / Sexuality settings is set to 'straight'?

With settings:

How to calculate sex? -> Creation Kit

I play as -> Straight

Use SexLab sexuality for NPCs -> No

..what little testing I did with a simple male on female rule, it seemed to pair male and female actors.

 

 

I don't use PC as actor for Scent of Sex, rest of the settings set as you suggested (I tried different combinations as well).

 

 

The most important setting would be the 'I play as: Straight' I think since I don't think NPCs generally define sexlab gender separately, and as long as you've set the correct player gender in sexlab It shouldn't matter if your PC was set to use sexlab or CK gender if you used it in rules.  The 'I play as' affects all rules though, based on description.. as long as that one's set to 'Straight' (which I think was default), it should work right.  At least it did for me.

 

Posted

 

 

On a sidenote, why do i have to manually activate 99% of the creature races again every time start the mod? Its annoying

 

Try to manually clean up the Scent of Sex Config.json.

 

Delete completely the section "races" : {...}

Save the json file and try.

 

 

there is no such section in the config file...

 

 

Then something is wrong.  Are you using mod organizer, is the config file somewhere with write access?  If you do use MO, did you remember to move the config file away from overwrite folder?

 

The races section at least for me, is right after the 'nudity' and before 'rules'.

 

 

 

    "nudity" :
    {
        "armorKeywords" : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
        "nakedBody" : 2,
        "nakedCalves" : 2,
        "nakedFeet" : 2,
        "nakedForearms" : 2,
        "nakedHands" : 2,
        "nakedHead" : 2,
        "nakedMinLevel" : 0,
        "nakedPelvis" : 2
    },
    "races" :
    {
        "creatures" :
        {
            "enabled" :
            [
                1,
                0,
                0,
                1,
                1,
                1,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ],
            "races" :
            [
                "Ashhoppers",
                "AtronachFrost",
                "AtronachStorm",
                "Bears",
                "Boars",
                "Centurions",
                "Chart Horses",
                "Chaurus",
                "Chaurusflyers",
                "Chickens",
                "Cows",
                "Deers",
                "Dogpanic",
                "Dogs",
                "Dragons",
                "Draugrs",
                "Falmers",
                "FlameAtronach",
                "Gargoyles",
                "Giants",
                "Goats",
                "Hagravens",
                "Horkers",
                "Horses",
                "Horseses",
                "LargeSpiders",
                "Lurkers",
                "Mammoths",
                "Netches",
                "Rabbits",
                "Rieklings",
                "SabreCats",
                "Seekers",
                "Skeevers",
                "Spiders",
                "Spriggans",
                "SprigganXan",
                "Trolls",
                "VampireLords",
                "Werewolfgal",
                "Werewolfpanic",
                "Werewolves",
                "Wispmothers",
                "Wolfpanic",
                "Wolves"
            ]
        },
        "humans" :
        {
            "enabled" : [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],
            "races" :
            [
                "Argonian",
                "Breton Vampire",
                "Breton",
                "DarkElf",
                "DarkElf Vampire",
                "DarkElfAmbriel",
                "Elder",
                "Elder Vampire",
                "HighElf",
                "HighElf Vampire",
                "IMPERIAL",
                "IMPERIAL Vampire",
                "Khajiit",
                "Khajiit Vampire",
                "Manakin",
                "Nord",
                "Nord Astrid",
                "Nord Vampire",
                "Orc Vampire",
                "Orc",
                "Redguard",
                "Redguard Vampire",
                "WoodElf",
                "WoodElf Vampire"
            ]
        }
    },
    "rules" :
    [
        {
            "animsAndTags" :

 

 

Posted

Triple post (duh), but didn't want to mix my own tests with replies to others.

 

First, when lowering number of rules from 24 to 8, the mod keeps complaining there's 24 rules in config file - even though I've deleted rules so I actually only have 5 or so.  Would be nice if the mod cleaned out empty rules from config save.  I cleared the old rules manually, that made the problem go away.

 

Second, I've kept saying the mod runs way too slowly for situational triggers like health triggers (taking over 30 seconds from triggering event to rule actually firing and stopping combat).  It makes health rules basically impossible to use, and when I'm going around with companion, it also makes it so when I drop into bleedout, it's permanet - the companion kills the opponent before rule has time to start a scene and subsequently remove the bleedout.

 

But I'd never actually ran the performance test before.. finally got to it.  The results:

 

Ran 'baseline' in forest outside whiterun with SSX inactive.  Results looked fine:

 

post-435442-0-54999500-1476237844_thumb.jpg

 

Then went into whiterun, and fired up SSX in alias scan mode.  I had 3 rules active, all bleedout based.  Phase 1 went fast, Phase 2 never finished.  I waited for half an hour, then gave up.

 

Went back to unmodified version G, to make sure it's nothing to do with the changes I'd made.  Reduced number of rules to 8 at this point, made scans more infrequent, changed scene triggers to happen more rarely.  Started test again, the result was same - after another half an hour I gave up.  Here's papyrus log from running the test:

 

Papyrus.0.log

 

And the SSX config file:

 

Scent of Sex Config.json

 

-------------------- edit --------------------------

 

Did the test with almost new save, and results were different.  Did baseine in qasmoke this time, the results are on left statistics.  Ran the test with mod active, still in qasmoke, the results were identical.  Stopped mod, moved inside whiterun, restarted mod.  Ran the test inside whiterun with mod active, the results are in the right box - very little performance hit.

 

post-435442-0-74663800-1476239587_thumb.jpg

 

However this is the character I usually run the tests with (one named 'test', duh), so I'm still getting the huge performance lag from health rules.  Anyway, adding the papyrus log from this test run too, the config file was exact same as before.

 

Papyrus.0.log

Posted

Thanks for the reports @reikiri, I will try to find and solve the problems this weekend. (Some look easy (Health, Number of Rules), some not too much.)

Posted

So....

 

The MCM menu never showed up. I waited for quite a bit.

 

I have a hundreds of mods installed, Frostfall included. It is possible that the scripts never had time to work on the MCM menu, but I do not think so. I had it run for twenty minutes.

 

There is a small bit of my papyrus log below. It is the only part with errors. The rest of the 4000 lines is warnings, mostly from SSX.

 

I am now deleting the files, and I will clean the save. I think I will try again after a while.

 

Any ideas?

 

 

 

[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "slaf" on object "ssxrunner"
[10/11/2016 - 07:38:11PM] Error: Unable to link types associated with function "weHaveSLA" in state "" on object "ssxrunner".
[10/11/2016 - 07:38:11PM] Error: Unable to link types associated with function "getArousalLevel" in state "" on object "ssxrunner".
[10/11/2016 - 07:38:11PM] Error: Unable to link types associated with function "DoInit" in state "" on object "ssxrunner".
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxMCM"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxMCM"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxplayerloadsgame"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxplayerloadsgame"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxdeferredconfigloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxdeferredconfigloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link types associated with function "loadSSXConfig" in state "" on object "ssxdeferredconfigloader".
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxdeferredtagsloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxdeferredtagsloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxruleplayer"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxruleplayer"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxdeferredmodsloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxdeferredmodsloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxcellscanner"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxcellscanner"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxdeferreditemsloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxdeferreditemsloader"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxrulechecker"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxrulechecker"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxeventcatcher"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxeventcatcher"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxaliasscan"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxaliasscan"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of variable "::ssx_var" on object "ssxscenemanager"
[10/11/2016 - 07:38:11PM] Error: Unable to link type of property "ssx" on object "ssxscenemanager"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssxPlayerCellDetectorScript"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssxPlayerCellDetectorScript"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_PF_ssxAskForCreatureSex_0400388C"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_PF_ssxAskForCreatureSex_0400388C"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_PF_ssxAskForCreatureSex_0400388C to  (9900388C) because their base types do not match
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_SF_ssxScene2_0306177A"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssxSM_var" on object "ssx_SF_ssxScene2_0306177A"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssxSM" on object "ssx_SF_ssxScene2_0306177A"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_SF_ssxScene2_0306177A"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_SF_ssxScene2_0306177A to  (9906177A) because their base types do not match
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_SF_ssxScene4_0306630D"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssxSM_var" on object "ssx_SF_ssxScene4_0306630D"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssxSM" on object "ssx_SF_ssxScene4_0306630D"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_SF_ssxScene4_0306630D"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_SF_ssxScene4_0306630D to  (9906630D) because their base types do not match
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssxSM_var" on object "ssx_SF_ssxScenePlayerAsk_0304FF01"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_SF_ssxScenePlayerAsk_0304FF01"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssxSM" on object "ssx_SF_ssxScenePlayerAsk_0304FF01"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_SF_ssxScenePlayerAsk_0304FF01"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_SF_ssxScenePlayerAsk_0304FF01 to  (9904FF01) because their base types do not match
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssxSM_var" on object "ssx_SF_ssxScene5_0306630E"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_SF_ssxScene5_0306630E"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssxSM" on object "ssx_SF_ssxScene5_0306630E"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_SF_ssxScene5_0306630E"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_SF_ssxScene5_0306630E to  (9906630E) because their base types do not match
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssxSM_var" on object "ssx_SF_ssxScene3_0306630C"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_SF_ssxScene3_0306630C"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssxSM" on object "ssx_SF_ssxScene3_0306630C"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_SF_ssxScene3_0306630C"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_SF_ssxScene3_0306630C to  (9906630C) because their base types do not match
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssx_var" on object "ssx_SF_ssxScenePlayerAsked_0305D6B5"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of variable "::ssxSM_var" on object "ssx_SF_ssxScenePlayerAsked_0305D6B5"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssxSM" on object "ssx_SF_ssxScenePlayerAsked_0305D6B5"
[10/11/2016 - 07:38:12PM] Error: Unable to link type of property "ssx" on object "ssx_SF_ssxScenePlayerAsked_0305D6B5"
[10/11/2016 - 07:38:12PM] Error: Unable to bind script ssx_SF_ssxScenePlayerAsked_0305D6B5 to  (9905D6B5) because their base types do not match
[10/11/2016 - 07:38:15PM] Error: Unable to bind script LycHairstyleScript to Item 1 in container  (4600183A) because their base types do not match
[10/11/2016 - 07:38:33PM] Error: Property slave_stub on script PAHActorAlias attached to alias slave_stub on quest PAH (0A01FAEF) cannot be bound because alias slave_stub on quest PAH (0A01FAEF) is not the right type
[10/11/2016 - 07:38:33PM] Error: Property ReleaseMarker on script pahslave attached to alias slave on quest PAH (0A01FAEF) cannot be bound because  (00015DFD) is not the right type
[10/11/2016 - 07:38:33PM] Error: Unable to bind script AN_PalaceNoteStartQuestScript to alias QueenNote on quest An_PalaceQuest (480B2515) because their base types do not match
[10/11/2016 - 07:38:33PM] warning: Property ArmorFFSelf0 on script ValiaDeathScript attached to alias Valia on quest ValiaDialogue (5600D261) cannot be initialized because the script no longer contains that property
[10/11/2016 - 07:38:33PM] warning: Property BoundEbonyArmor on script ValiaDeathScript attached to alias Valia on quest ValiaDialogue (5600D261) cannot be initialized because the script no longer contains that property
[10/11/2016 - 07:38:33PM] Error: Property DialogueFollower on script FollowerAliasScript attached to alias Follower on quest 0_knm_mour_dialogue_all (59007945) cannot be bound because 0_knm_mour_dialogue_all (59007945) is not the right type
[10/11/2016 - 07:38:33PM] Error: Property DialogueFollower on script TrainedAnimalScript attached to alias Animal on quest 0_knm_mour_dialogue_all (59007945) cannot be bound because 0_knm_mour_dialogue_all (59007945) is not the right type
[10/11/2016 - 07:38:33PM] warning: Property FCQuest01 on script FCStartQuest attached to alias Note on quest 000FCQuest01 (5F012BB9) cannot be initialized because the script no longer contains that property
[10/11/2016 - 07:38:33PM] Error: Unable to bind script EtC_BellaScript to alias EtC_BellaAlias on quest ExitTheCell (7D001837) because their base types do not match
[10/11/2016 - 07:38:33PM] Error: Unable to bind script EtC_BellaScript to alias EtC_BellaAlias on quest EtC_BurnedCabin (7D023BD8) because their base types do not match
[10/11/2016 - 07:38:33PM] warning: Property ssx on script ssxeventcatcher attached to alias eventCatcherB on quest ssxRC (990304BE) cannot be initialized because the script no longer contains that property
[10/11/2016 - 07:38:33PM] warning: Property ssx on script ssxeventcatcher attached to alias eventCatcherB031 on quest ssxRC (990304BE) cannot be initialized because the script no longer contains that property

 

 

Posted

Thanks for the reports @reikiri, I will try to find and solve the problems this weekend. (Some look easy (Health, Number of Rules), some not too much.)

 

Glad if I've been able to help.  Here's one more test and one more log that showcases a few things I've mentioned, and also added a lot of debug.trace notes to the rulechecker PlayRule event - which might possibly help trace what's actually going on.

 

Modified event catcher:

 

 

Scriptname ssxEventCatcher extends ReferenceAlias ; V1.3



ssxRunner Property ssx Auto

; MODIFIED

bool checkHealth

; !MODIFIED

Actor lastAggressor

Float lastUndress

bool wasINaked

bool catchBleed

int[] ruleIDsB

bool catchNaked

int[] ruleIDsN

bool catchWeapon

int[] ruleIDsW

bool catchCombat

int[] ruleIDsC

bool catchSleep

int[] ruleIDsS

bool catchHealth

int[] catchHealthLevs ; Level of healt, >=0 then as to be greater, <0 has to be less than

int[] ruleIDsH



Event OnInit()

    ruleIDsB = new int[4]

    ruleIDsN = new int[4]

    ruleIDsW = new int[4]

    ruleIDsC = new int[4]

    ruleIDsS = new int[4]

    ruleIDsH = new int[4]

    catchHealthLevs = new int[4]

    lastUndress = -1.0

    wasINaked=false

; MODIFIED

    checkHealth=true

; !MODIFIED

endEvent



Event OnUpdate()

; MODIFIED

    checkHealth = true

; !MODIFIED

EndEvent



Function init(bool bleedout, bool naked, bool weap, bool combat, bool sleep, bool health, int[] BRuleIDs, int[] NRuleIDs, int[] WRuleIDs, int[] CRuleIDs, int[] SRuleIDs, int[] HRuleIDs, int[] healthLevs)

    catchBleed = bleedout

    int i = ruleIDsB.length

    while i

        i-=1

        ruleIDsB[i] = BRuleIDs[i]

    endWhile

    

    catchNaked = naked

    i = ruleIDsN.length

    while i

        i-=1

        ruleIDsN[i] = NRuleIDs[i]

    endWhile

    

    catchWeapon = weap

    i = ruleIDsW.length

    while i

        i-=1

        ruleIDsW[i] = WRuleIDs[i]

    endWhile

    

    catchCombat = combat

    i = ruleIDsC.length

    while i

        i-=1

        ruleIDsC[i] = CRuleIDs[i]

    endWhile

    

    catchSleep = sleep

    i = ruleIDsS.length

    while i

        i-=1

        ruleIDsS[i] = SRuleIDs[i]

    endWhile

    if sleep

        RegisterForSleep()

    else

        UnregisterForSleep()

    endIf

    

    catchHealth = health

    i = ruleIDsH.length

    while i

        i-=1

        ruleIDsH[i] = HRuleIDs[i]

        catchHealthLevs[i] = healthLevs[i]

    endWhile

    

    lastAggressor = None

    lastUndress = -1.0

    wasINaked=false

; MODIFIED

    checkHealth=true

    UnregisterForUpdate()

; !MODIFIED

EndFunction



Function clean()

    UnregisterForSleep()

    ruleIDsB = new int[4]

    ruleIDsN = new int[4]

    ruleIDsW = new int[4]

    ruleIDsC = new int[4]

    ruleIDsS = new int[4]

    ruleIDsH = new int[4]

    catchHealthLevs = new int[4]

    lastAggressor = None

    lastUndress = -1.0

    wasINaked=false

; MODIFIED

    checkHealth=true

    UnregisterForUpdate()

; !MODIFIED

EndFunction





; ((- Events **********************************************************************************************************************************





; aeCombatState: 0=not in combat, 1=in combat, 2=searching

Event OnCombatStateChanged(Actor akTarget, int aeCombatState)

    if catchCombat && aeCombatState!=0

        ssx.updateMe(self.getActorReference(), None)

        triggerRules(ruleIDsC, 4)

    endIf

EndEvent







Event OnSleepStart(float afSleepStartTime, float afDesiredSleepEndTime)

    if catchSleep

        ssx.updateMe(self.getActorReference(), None)

        triggerRules(ruleIDsS, 6)

    endIf

endEvent



Event OnEnterBleedout()

    if catchBleed

        ssx.updateMe(self.getActorReference(), None)

        triggerRules(ruleIDsB, 5)

    endIf

EndEvent



Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)

    lastAggressor = akAggressor as Actor

    ; MODIFIED

    if (!catchHealth)

        return

    endIf

    if (!checkHealth)

        debug.trace("## SUPPRESSING HEALTH EVENT CALL")

        return

    endIf

    checkHealth = false

    registerForSingleUpdate(2.0)

    ; !MODIFIED

    int h = ssx.getHealthLevel(Self.getActorReference())

    int i = 4

    while i

        i-=1

        int ch = catchHealthLevs[i]

        if (ch<0 && h< -ch) || (ch>=0 && h>=ch)

    ; MODIFIED

debug.trace("## TRIGGER ON HEALTH " + h + " AGAINST " + ch)

    ; !MODIFIED

            triggerRules(ruleIDsH, 3)

            return

        endIf

    endWhile

EndEvent



Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)

    if catchNaked

        Actor a = Self.getActorReference()

        float justNow = Utility.GetCurrentRealTime()

        bool amINaked = ssx.isActorNaked(a)

        if justNow-lastUndress < 10.0 || amINaked==wasINaked

            return

        endIf

        wasINaked=amINaked

        lastUndress = justNow

        ssx.updateMe(self.getActorReference(), None)

        if ssx.isActorNaked(a)

            ssx.updateMe(self.getActorReference(), None)

            triggerRules(ruleIDsN, 2)

        endIf

    endIf

EndEvent



Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)

    if catchNaked

        Actor a = Self.getActorReference()

        float justNow = Utility.GetCurrentRealTime()

        bool amINaked = ssx.isActorNaked(a)

        if justNow-lastUndress < 10.0 || amINaked==wasINaked

            return

        endIf

        wasINaked=amINaked

        lastUndress = justNow

        ssx.updateMe(self.getActorReference(), None)

        if ssx.isActorNaked(a)

            ssx.updateMe(self.getActorReference(), None)

            triggerRules(ruleIDsN, 2)

        endIf

    endIf

EndEvent





Function triggerRules(int[] ruleIDs, int catchMode) ; Send the event to play the rule for all registered rule IDs. This will fail because the actor may not be in the rule's participants

    ; catchMode: 0=unspecified (random), 1=player ask (not really an event), 2=nudity, 3=health, 4=combat, 5=bleedout, 6=sleep

; MODIFIED

debug.trace("## TRIGGER RULES MODE " + catchMode)

; !MODIFIED

    int handle = ModEvent.Create("ssxPlayRule")

    ModEvent.PushForm(handle, Self.getActorReference())

    ModEvent.PushForm(handle, lastAggressor)

    ModEvent.PushInt(handle, catchMode)

    ModEvent.PushInt(handle, ruleIDs[0])

    ModEvent.PushInt(handle, ruleIDs[1])

    ModEvent.PushInt(handle, ruleIDs[2])

    ModEvent.PushInt(handle, ruleIDs[3])

    ModEvent.Send(handle)

EndFunction



; -))

 

 

 

Modified rule checker "playRule" event:

 

 

    Event playRule(Form a, Form b, int catchMode, int r1, int r2, int r3, int r4)

        UnregisterForUpdate()

        ssx.dbg("Rule Checker: playing rules from Event Catchers", 0, "RuleChecker")

debug.trace("## RC001")        

        addActorAndStatus(a as Actor)

        addActorAndStatus(b as Actor)

        

        ; Try to fill the rule (any of the set), if at least one rule can be filled, then mark it as valid and call the Rule player

        if r4==0 && r3==0 && r2==0 && r1==0

            float time = Utility.randomFloat(ssx.ruleCheckerMinWaitTime, ssx.ruleCheckerMaxWaitTime)

            RegisterForSingleUpdate(time)

            ssx.dbg("Rule Checker - No event rules.", 0, "RuleChecker")

            return

        endIf

debug.trace("## RC002")        



        initActors() ; The status will be calclated and updated for all actors

        if allActorsNum==0

            float time = Utility.randomFloat(ssx.ruleCheckerMinWaitTime, ssx.ruleCheckerMaxWaitTime)

            RegisterForSingleUpdate(time)

            ssx.dbg("Rule Checker - No actors.", 0, "RuleChecker")

            return

        endIf

debug.trace("## RC003")        

    

        while ssx.letsWait

            Utility.wait(1.0)

        endWhile

        

        if ssx.countScenesPlaying()>=ssx.maxNumberOfParallelScenes

            ssx.dbg("Rule Checker - Too many scenes are already playing.", 0, "RuleChecker")

            float time = Utility.randomFloat(ssx.ruleCheckerMinWaitTime, ssx.ruleCheckerMaxWaitTime)

            RegisterForSingleUpdate(time)

            return

        endIf

debug.trace("## RC004")        



        ssxRule[] testRules

        if r4 && r3 && r2 && r1

            testRules = new ssxRule[4]

            testRules[0] = ssx.getRuleById(r1)

            testRules[1] = ssx.getRuleById(r2)

            testRules[2] = ssx.getRuleById(r3)

            testRules[3] = ssx.getRuleById(r4)

debug.trace("## RC005A")        

        elseIf r3 && r2 && r1

            testRules = new ssxRule[3]

            testRules[0] = ssx.getRuleById(r1)

            testRules[1] = ssx.getRuleById(r2)

            testRules[2] = ssx.getRuleById(r3)

debug.trace("## RC005B")        

        elseIf r2 && r1

            testRules = new ssxRule[2]

            testRules[0] = ssx.getRuleById(r1)

            testRules[1] = ssx.getRuleById(r2)

debug.trace("## RC005C")        

        elseIf r1

            testRules = new ssxRule[1]

            testRules[0] = ssx.getRuleById(r1)

debug.trace("## RC005D")        

        else

            float time = Utility.randomFloat(ssx.ruleCheckerMinWaitTime, ssx.ruleCheckerMaxWaitTime)

            RegisterForSingleUpdate(time)

            ssx.dbg("Rule Checker - No rules.", 0, "RuleChecker")

debug.trace("## RC005E")        

            return ; No rules

        endIf

        

        float justNow = Utility.GetCurrentGameTime()

        int hour = ((justNow - Math.floor(justNow)) * 24) as Int

        int numOfTheRules = 0

        bool foundValidRule = false

        int act

debug.trace("## RC006")                

        ; find which rule can be filled for real, with the specified actors (b may be empty)

        Actor p1 = a as Actor

        Actor p2 = b as Actor

        

        int i=testRules.length

        while i

            i-=1

            ssxRule r = testRules[i]

            if r && r.inUse==2 && \

debug.trace("## RC007A")        

                (r.timeBeforeReDo<=0.0 || r.lastRunTime<=0.0 || (justNow-r.lastRunTime)*3600.0>r.timeBeforeReDo) && \

                (r.getStartTimer(true)==-1 || (r.getStartTimer(true)<=r.getStartTimer(false) && r.getStartTimer(true)<=hour && r.getStartTimer(false)>=hour) || (r.getStartTimer(true)>r.getStartTimer(false) && (r.getStartTimer(true)>=hour || r.getStartTimer(false)<=hour)))

                ; Not in timeout, or timeout not required, and if the start time is specified then the hour is good

                ; Use the try to fill to get the Dsrt, Src, Coll, if possible then put the rule and the actors

                if tryToFillTheRule(r, p1, p2)

debug.trace("## RC007B")

                    ; OK, rule is good, put the values, each valid rule will get a position in the rules array

                    ; Check if the player will ask, in this case put the actors in the correct faction

                    Faction canBeAsked = None

                    if r.startsOn==1 ; Player asks

debug.trace("## RC007C")

                        canBeAsked = ssx.setUpPlayerDialogues(r)

                        ssx.rulesAskFactions[i] = canBeAsked

                    else

debug.trace("## RC007D")

                        ssx.rulesAskFactions[i] = None

                    endIf

                    r.setValidActors(0, dstActors, dstActorsLen, canBeAsked)

                    r.setValidActors(1, srcActors, srcActorsLen, canBeAsked)

                    if canBeAsked && Math.LogicalAnd(ssx.notifHighlight, 0x10)

debug.trace("## RC007E")

                        int color = r.getHighlightColor(0, true)

                        if color

debug.trace("## RC007F")

                            act=dstActorsLen

                            while act

                                act-=1

                                ssx.hlg(dstActors[act], color, "Askable")

                            endWhile

                        endIf

                        color = r.getHighlightColor(1, true)

                        if color

debug.trace("## RC007G")

                            act=srcActorsLen

                            while act

                                act-=1

                                ssx.hlg(srcActors[act], color, "Askable")

                            endWhile

                        endIf

                    endIf

                    r.setValidActors(2, collActors, collActorsLen, None)

                    if r.startsOn==0 ; Only Random starting can be automatic

debug.trace("## RC007H")

                        foundValidRule = true

                    endIf

                    numOfTheRules+=1

                    ssx.putValidRule(r)

                    

                    ; Actor highlights, if required

                    int color = r.getHighlightColor(0, true)

                    if color

debug.trace("## RC007I")

                        act=dstActorsLen

                        while act

                            act-=1

                            ssx.hlg(dstActors[act], color, "CheckingGood")

                        endWhile

                    endIf

                    color = r.getHighlightColor(1, true)

                    if color

debug.trace("## RC007J")

                        act=srcActorsLen

                        while act

                            act-=1

                            ssx.hlg(srcActors[act], color, "CheckingGood")

                        endWhile

                    endIf

                    color = r.getHighlightColor(2, true)

                    if color

debug.trace("## RC007K")

                        act=collActorsLen

                        while act

                            act-=1

                            ssx.hlg(collActors[act], color, "CheckingGood")

                        endWhile

                    endIf

                else

debug.trace("## RC007L")

                    ssx.removeValidRule(r)

                    testRules[i]=None

                endIf

            endIf

            

            if ssx.iAmActive==0

debug.trace("## RC007M")

                GoToState("inactive")

            endIf

            while ssx.letsWait

                Utility.wait(1.0)

            endWhile

        endWhile

        

        if foundValidRule

debug.trace("## RC008")

            ; Send the mod event

            int handle = ModEvent.Create("ssxPlayRulesNow")

            ModEvent.PushForm(handle, a)

            ModEvent.PushForm(handle, 

            ModEvent.PushInt(handle, catchMode)

            if testRules[0]

debug.trace("## RC008A")

                ModEvent.PushInt(handle, testRules[0].id)

            else

debug.trace("## RC008B")

                ModEvent.PushInt(handle, 0)

            endIf

            if testRules.length>1 && testRules[1]

debug.trace("## RC008C")

                ModEvent.PushInt(handle, testRules[1].id)

            else

debug.trace("## RC008D")

                ModEvent.PushInt(handle, 0)

            endIf

            if testRules.length>2 && testRules[2]

debug.trace("## RC008E")

                ModEvent.PushInt(handle, testRules[2].id)

            else

debug.trace("## RC008F")

                ModEvent.PushInt(handle, 0)

            endIf

            if testRules.length>3 && testRules[3]

debug.trace("## RC008G")

                ModEvent.PushInt(handle, testRules[3].id)

            else

debug.trace("## RC008H")

                ModEvent.PushInt(handle, 0)

            endIf

            ModEvent.Send(handle)

        endIf

        float time = Utility.randomFloat(ssx.ruleCheckerMinWaitTime, ssx.ruleCheckerMaxWaitTime)

        RegisterForSingleUpdate(time)

        ssx.dbg("Rule Checker - Rules checking on events completed. Found " + numOfTheRules + " valid rules. Restarting in " + (time as int) + " seconds.", 0, "RuleChecker")

debug.trace("## RC009")

    EndEvent   

 

 

 

Ran a test with the 'test' character in qasmoke, against cultist as usual, with added health trigger along with the bleedout rules.

 

 

 

[10/12/2016 - 05:46:23AM] SSX DEBUG: Alias Scanner - Scan completed. Found 2 actors

[10/12/2016 - 05:46:26AM] ## TRIGGER RULES MODE 4

[10/12/2016 - 05:46:26AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

[10/12/2016 - 05:46:26AM] ## RC001

[10/12/2016 - 05:46:27AM] ## RC002

[10/12/2016 - 05:46:28AM] ## RC003

[10/12/2016 - 05:46:28AM] ## RC004

[10/12/2016 - 05:46:28AM] ## RC005D

[10/12/2016 - 05:46:28AM] ## RC006

[10/12/2016 - 05:46:28AM] ## RC007A

[10/12/2016 - 05:46:28AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 38 seconds.

[10/12/2016 - 05:46:28AM] ## RC009

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## TRIGGER ON HEALTH 96 AGAINST 0

[10/12/2016 - 05:46:30AM] ## TRIGGER RULES MODE 3

[10/12/2016 - 05:46:30AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

[10/12/2016 - 05:46:30AM] ## RC001

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:31AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:31AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:31AM] ## TRIGGER RULES MODE 4

[10/12/2016 - 05:46:31AM] ## TRIGGER RULES MODE 5

[10/12/2016 - 05:46:31AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

[10/12/2016 - 05:46:31AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

[10/12/2016 - 05:46:31AM] ## RC001

[10/12/2016 - 05:46:31AM] ## RC001

[10/12/2016 - 05:46:31AM] ## RC002

[10/12/2016 - 05:46:32AM] ## RC002

[10/12/2016 - 05:46:33AM] ## RC003

[10/12/2016 - 05:46:33AM] ## RC004

[10/12/2016 - 05:46:33AM] ## RC005D

[10/12/2016 - 05:46:33AM] ## RC006

[10/12/2016 - 05:46:33AM] ## RC007A

[10/12/2016 - 05:46:33AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 43 seconds.

[10/12/2016 - 05:46:33AM] ## RC009

[10/12/2016 - 05:46:34AM] ## RC003

[10/12/2016 - 05:46:34AM] ## RC004

[10/12/2016 - 05:46:34AM] ## RC005D

[10/12/2016 - 05:46:34AM] ## RC006

[10/12/2016 - 05:46:34AM] ## RC007A

[10/12/2016 - 05:46:34AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 36 seconds.

[10/12/2016 - 05:46:34AM] ## RC009

[10/12/2016 - 05:46:34AM] ## RC002

[10/12/2016 - 05:46:35AM] ## RC003

[10/12/2016 - 05:46:35AM] ## RC004

[10/12/2016 - 05:46:35AM] ## RC005D

[10/12/2016 - 05:46:35AM] ## RC006

[10/12/2016 - 05:46:35AM] ## RC007A

[10/12/2016 - 05:46:35AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 39 seconds.

[10/12/2016 - 05:46:35AM] ## RC009

 

 

 

- You're right, single events from event catcher are fast.  If the fight isn't totally overwhelming, then in best conditions at least, they are fast enough.  This though, is in qasmoke, so there's nothing else to tax the system.  On the other hand I'm running this with PerMa so there's comparatively heavy scripts firing up during the fight, vanilla game would be lighter.

 

 

 

[10/12/2016 - 05:46:26AM] ## TRIGGER RULES MODE 4

 

 

 

- Combat starts

 

 

 

[10/12/2016 - 05:46:28AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 38 seconds.

 

 

 

- Check finished, two seconds.

 

 

 

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## TRIGGER ON HEALTH 96 AGAINST 0

[10/12/2016 - 05:46:30AM] ## TRIGGER RULES MODE 3

[10/12/2016 - 05:46:30AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

 

 

 

- health falls below limit.  I think the first suppress is actually second time the rule triggers, but they are processed in opposite order

 

 

 

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:30AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:31AM] ## SUPPRESSING HEALTH EVENT CALL

[10/12/2016 - 05:46:31AM] ## SUPPRESSING HEALTH EVENT CALL

 

 

 

- 10 more hits from the flame spell, every one of these would have started another event

 

 

 

[10/12/2016 - 05:46:31AM] ## TRIGGER RULES MODE 4

[10/12/2016 - 05:46:31AM] ## TRIGGER RULES MODE 5

[10/12/2016 - 05:46:31AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

[10/12/2016 - 05:46:31AM] SSX DEBUG: Rule Checker: playing rules from Event Catchers

 

 

 

- combat stops

- because bleedout.  with companion, it would continue of course

 

 

 

[10/12/2016 - 05:46:31AM] ## RC001

[10/12/2016 - 05:46:31AM] ## RC001

[10/12/2016 - 05:46:31AM] ## RC002

[10/12/2016 - 05:46:32AM] ## RC002

[10/12/2016 - 05:46:33AM] ## RC003

[10/12/2016 - 05:46:33AM] ## RC004

[10/12/2016 - 05:46:33AM] ## RC005D

[10/12/2016 - 05:46:33AM] ## RC006

[10/12/2016 - 05:46:33AM] ## RC007A

[10/12/2016 - 05:46:33AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 43 seconds.

[10/12/2016 - 05:46:33AM] ## RC009

[10/12/2016 - 05:46:34AM] ## RC003

[10/12/2016 - 05:46:34AM] ## RC004

[10/12/2016 - 05:46:34AM] ## RC005D

[10/12/2016 - 05:46:34AM] ## RC006

[10/12/2016 - 05:46:34AM] ## RC007A

[10/12/2016 - 05:46:34AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 36 seconds.

[10/12/2016 - 05:46:34AM] ## RC009

[10/12/2016 - 05:46:34AM] ## RC002

[10/12/2016 - 05:46:35AM] ## RC003

[10/12/2016 - 05:46:35AM] ## RC004

[10/12/2016 - 05:46:35AM] ## RC005D

[10/12/2016 - 05:46:35AM] ## RC006

[10/12/2016 - 05:46:35AM] ## RC007A

[10/12/2016 - 05:46:35AM] SSX DEBUG: Rule Checker - Rules checking on events completed. Found 0 valid rules. Restarting in 39 seconds.

[10/12/2016 - 05:46:35AM] ## RC009

 

 

 

- health, combat stop and bleedout processed in parallel.  problem is none of them match.  I think I added 'source in combat' to bleedout rule, but since bleedout stopped combat in this case, it won't match.  Total time to process 5 seconds, which in case of health rule in many cases would not make it in time.  If the other 10 triggers had sent an event, the papyrus would probably have choked on them like it did on my earlier tests.

 

 

 

[10/12/2016 - 05:47:15AM] SSX DEBUG: Rule Checker - Starting the checking

[10/12/2016 - 05:47:16AM] slaScanner start time is ....240.858994

[10/12/2016 - 05:47:16AM] SSX DEBUG: Rule Checker: Trying to fill the rule: health rule

[10/12/2016 - 05:47:16AM] Found 1 arousedActors

[10/12/2016 - 05:47:17AM] SSX DEBUG: Adding test to health rule pos=0

 Ma=False Fo=False Hu=TRUE Na=TRUE SN=TRUE SS=TRUE AR=TRUE/40 he=TRUE/-1 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=TRUE Unc=False race=Silvan

[10/12/2016 - 05:47:17AM] Found 0 nakedActors

[10/12/2016 - 05:47:17AM] slaScanner After getting actors is ....241.707001, player is naked TRUE, Actor Count 1

[10/12/2016 - 05:47:17AM] [slainternalscr <sla_Internal (10083137)>]: Cultist got 8 exposure for  seeing naked test

[10/12/2016 - 05:47:17AM] slaScanner end time is ....242.225998

[10/12/2016 - 05:47:17AM] Next update in 120.000000

[10/12/2016 - 05:47:18AM] SSX DEBUG: Adding Cultist to health rule pos=1

 Ma=TRUE Fo=False Hu=TRUE Na=False SN=TRUE SS=TRUE AR=TRUE/20 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Nord

[10/12/2016 - 05:47:18AM] SSX DEBUG: GOOD rule, it can be filled: health rule

 

 

 

- later on, the health rule is checked again by rule checker in regular scan.  This time it matches, and the rule will play.  So in this case the delay didn't come from the event being slow to process, but rather from needing to wait for the timed scan for the trigger.

 

- why doesn't the health rule trigger?  I have no idea.  Maybe it's connected to changes I made to rule checker to make the timed health/stamina/magicka rules trigger in expected way (and they do, now), but I don't know the full layout of the mod well enough to be sure.  The changes I made:

 

 

 

            if isGood && ssx.weHaveSLA() ; Arousal

                mode = r.getPositionStartMode(ssxRule.getSMArousal(), pos)

                if (mode==1 && ar<r.arousalLevel) || (mode==2 && ar>=r.arousalLevel)

                    ssx.dbg("Actor is bad because arousal: " + a.getDisplayName() + " Level=" + ar + " pos=" + pos, 7, "RuleChecker")

                    isGood = false

                endIf

                isAR = isGood

            endIf

; MODIFIED        

            if isGood ; Health

                mode = r.getPositionStartMode(ssxRule.getSMHealth(), pos)

                if (mode==1 && he<r.healthLevel) || (mode==2 && he>=r.healthLevel)

                    ssx.dbg("Actor is bad because health: " + a.getDisplayName() + " Level=" + he + " pos=" + pos, 7, "RuleChecker")

                    isGood = false

                endIf

                isHE = isGood

            endIf

        

            if isGood ; Stamina

                mode = r.getPositionStartMode(ssxRule.getSMStamina(), pos)

                if (mode==1 && st<r.staminaLevel) || (mode==2 && st>=r.staminaLevel)

                    ssx.dbg("Actor is bad because stamina: " + a.getDisplayName() + " Level=" + st + " pos=" + pos, 7, "RuleChecker")

                    isGood = false

                endIf

                isST = isGood

            endIf

        

            if isGood ; Magicka

                mode = r.getPositionStartMode(ssxRule.getSMMagicka(), pos)

                if (mode==1 && ma<r.magickaLevel) || (mode==2 && ma>=r.magickaLevel)

                    ssx.dbg("Actor is bad because magicka: " + a.getDisplayName() + " Level=" + ma + " pos=" + pos, 7, "RuleChecker")

                    isGood = false

                endIf

                isMA = isGood

            endIf

; !MODIFIED        

            if isGood ; sleep

                mode = r.getPositionStartMode(ssxRule.getSMSleep(), pos)

                if (mode==1 && !isSl) || (mode==2 && isSl)

                    ssx.dbg("Actor is bad because sleeping: " + a.getDisplayName() + " pos=" + pos, 7, "RuleChecker")

                    isGood = false

                endIf

            endIf

 

 

 

 

 

[10/12/2016 - 05:47:18AM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player defeat by creature

[10/12/2016 - 05:47:18AM] SSX DEBUG: Adding test to Player defeat by creature pos=0

 Ma=False Fo=False Hu=TRUE Na=TRUE SN=TRUE SS=TRUE AR=TRUE/40 he=TRUE/-1 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=TRUE Unc=False race=Silvan

[10/12/2016 - 05:47:19AM] SSX DEBUG: Actor is bad for its humanity: Cultist pos=1

[10/12/2016 - 05:47:19AM] SSX DEBUG: Bad rule because 6 - no sources - Player defeat by creature

[10/12/2016 - 05:47:19AM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player defeat by human

[10/12/2016 - 05:47:19AM] SSX DEBUG: Adding test to Player defeat by human pos=0

 Ma=False Fo=False Hu=TRUE Na=TRUE SN=TRUE SS=TRUE AR=TRUE/40 he=TRUE/-1 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=TRUE Unc=False race=Silvan

[10/12/2016 - 05:47:20AM] SSX DEBUG: Actor is bad because combat: Cultist pos=1

[10/12/2016 - 05:47:20AM] SSX DEBUG: Bad rule because 6 - no sources - Player defeat by human

[10/12/2016 - 05:47:20AM] SSX DEBUG: Rule Player: playing rules

[10/12/2016 - 05:47:20AM] SSX DEBUG: Rule Checker - Rules checking completed. Found 1 valid rules. Restarting in 48 seconds.

[10/12/2016 - 05:47:21AM] SSX: Rule: health rule with test and Cultist

[10/12/2016 - 05:47:21AM] SSX: Target: test Source: Cultist

[10/12/2016 - 05:47:21AM] SSX DEBUG: Combats stopped

 

 

 

- in this case, need to wait for the rest of the rules to get processed before the one to play is picked, and combat stopped.

 

 

 

[10/12/2016 - 05:47:25AM] SSX DEBUG: Animation is Zyn Rough Standing

[10/12/2016 - 05:47:25AM] SEXLAB - ActorAlias[Cultist]  - Waited [1] cycles for MarkerRef[[ObjectReference < (FF00134B)>]]

[10/12/2016 - 05:47:25AM] SEXLAB - ActorAlias[test]  - Waited [1] cycles for MarkerRef[[ObjectReference < (FF00134C)>]]

[10/12/2016 - 05:47:25AM] SEXLAB - ActorAlias[Cultist]  - Strip: [True, True, True, True, True, False, False, True, True, True, False, True, False, False, False, True, True, True, False, True, False, False, False, True, True, False, True, True, True, True, False, False, True]

[10/12/2016 - 05:47:26AM] SEXLAB - ActorAlias[test]  - Strip: [True, True, True, True, True, False, False, True, True, True, False, True, False, False, False, True, True, True, False, True, False, False, False, True, True, False, True, True, True, True, False, False, True]

[10/12/2016 - 05:47:27AM] SEXLAB - ActorAlias[test]  - Equipment: []

[10/12/2016 - 05:47:27AM] SEXLAB - ActorAlias[Cultist]  - Equipment: [[Form < (04037B88)>], [Armor < (04037B8A)>], [Form < (04037B8C)>], [Form < (04037B8E)>], [Form < (0007231A)>], [Form < (000C969A)>]]

[10/12/2016 - 05:47:27AM] SEXLAB - ActorAlias[test]  - Scales[1.000000/1.000000/1.000000] Voice[Breathy (Female)] Expression[Shy] BaseEnjoyment[0]

[10/12/2016 - 05:47:27AM] SEXLAB - ActorAlias[Cultist]  - Scales[1.030000/1.030000/0.970874] Voice[Average (Male)] Expression[Sad] BaseEnjoyment[0]

[10/12/2016 - 05:47:27AM] Error: Cannot move the player because they are dead

stack:

    [ (00000014)].Actor.SetPosition() - "<native>" Line ?

    [alias ActorAlias004 on quest SexLabThread00 (0F061EEF)].sslActorAlias.OnUpdate() - "sslActorAlias.psc" Line ?

[10/12/2016 - 05:47:27AM] Error: Cannot rotate the player because they are dead

stack:

    [ (00000014)].Actor.SetAngle() - "<native>" Line ?

    [alias ActorAlias004 on quest SexLabThread00 (0F061EEF)].sslActorAlias.OnUpdate() - "sslActorAlias.psc" Line ?

[10/12/2016 - 05:47:27AM] SEXLAB - Thread[0] SyncDone(Prepare) - Lag Timer: 27.682007

[10/12/2016 - 05:47:27AM] SEXLAB - Thread[0] Event Hook - AnimationStart

[10/12/2016 - 05:47:27AM] [Zad]: OnAnimationStart()

 

 

 

- this is what I'd mentioned earlier - moving and aligning player fails because they are dead (since health isn't restored at this point).

 

Full papyrus log of that test here, in case it's needed:

Papyrus.0.log

 

-- edit --

added small report to EventCatcher's "init" function when adding health rules:

    while i
        i-=1
        ruleIDsH[i] = HRuleIDs[i]
        catchHealthLevs[i] = healthLevs[i]
        debug.trace("I am catching health level of " + healthLevs[i])
    endWhile

With health rule active, got this on papyrus log:

[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0
[10/12/2016 - 08:38:31AM] I am catching health level of 0

There should have been health rule with "when health < 90%" so something doesn't look right here.

 

-- end edit--

-- edit 2 --

I'm not sure if I understand the work of RuleChecker correctly.. but from what I gathered..

- setUpCatchers() loops through every rule

- for each rule if it checks every position, and if it requires catcher it sends that rule for filterAndAddActor()

- for each such position filterAndAddActor loops through all known actors, and if it could match, sends it to addIt()

- addIt checks if the actor is already set to be handed catcher for that rule type - if so it doesn't care?

-- thus if actor is set to be monitored for being health < 30, source creature, it'll no longer be interesting for health rules that say < 80 source human?

-- if actor wasn't on list, (Captain, what should we do.. she's not on the list?)...

--- will be added to first null position, and trigger rule list is checked for including on the list if it wasn't there

--- if rule wasn't on the list, it will be added there too

--- size of the list is 4, so no more than 4 rules can be checked for particular even type

--- regardless of rule type, the health setting of the rule is checked (can be 0), and the index of the rule on their own ruletype list (f.ex. is naked?), is used to overwrite the health level value behind that index?

 

If I got it right, I guess I'm seeing the problem here.

-- end edit 2 --

-- edit 3 --

Quick fix that seems to apply the health rules as I believe they're meant to work.  Changed also the addIt to still check for additional rules to add even if actor already was listed - becasue f.ex. player can be part of bleedout rule for humans AND bleedout rule for creatures.  Rules are triggering now, and sex is happening.  :D :D :D

 

Also changed the >= part in EventCatcher into > because healthLevs has 4 values that may be zeroes - and don't want to trigger empty health rules when actor's health is >= 0. 

 

 

Function addIt(Actor a, int ruleID, Actor[] catchActs, int[] catchRuleIDs, int hl)
; MODIFY ------------------
    if catchRuleIDs == catchHealthRuleIDs
        addItHealth(a, ruleID, catchActs, catchRuleIDs, hl)
        return
    endIf
    if catchActs.find(a)==-1
        int i = catchActs.find(None)
        if i!=-1
            catchActs[i]=a
        endIf
    endIf
    if catchRuleIDs.find(ruleID)==-1
        int i = catchRuleIDs.find(0)
        if i!=-1
            catchRuleIDs[i]=ruleID
        endIf
    endIf
; MODIFY ------------------
EndFunction


; MODIFY ------------------
Function addItHealth(Actor a, int ruleID, Actor[] catchActs, int[] catchRuleIDs, int hl)
    if catchActs.find(a)==-1
        int i = catchActs.find(None)
        if i!=-1
            catchActs[i]=a
        endIf
    endIf
    if catchRuleIDs.find(ruleID)==-1
        int i = catchRuleIDs.find(0)
        if i!=-1
            debug.trace("## I'm setting up health levels for rule " + ruleID + " index " + i + " as hl " + hl)
            catchRuleIDs[i]=ruleID
            catchHealthLevs[i]=hl
            debug.trace("## for index " + i + " catchRuleIDs is " + catchRuleIDs[i] + " and catchHealthLevs is " + catchHealthLevs[i] + "; first 0 index is " + catchRuleIDs.find(0))
            debug.trace("## length of catchRuleIDs is " + catchRuleIDs.length)
        endIf
    endIf
EndFunction
; MODIFY ------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
    lastAggressor = akAggressor as Actor
    ; MODIFIED
    if (!catchHealth)
        return
    endIf
    if (!checkHealth)
        debug.trace("## SUPPRESSING HEALTH EVENT CALL")
        return
    endIf
    checkHealth = false
    registerForSingleUpdate(2.0)
    ; !MODIFIED
    int h = ssx.getHealthLevel(Self.getActorReference())
    int i = 4
    while i
        i-=1
        int ch = catchHealthLevs[i]
    ; MODIFIED
        if (ch<0 && h< -ch) || (ch>0 && h>=ch)
debug.trace("## TRIGGER ON HEALTH " + h + " AGAINST " + ch)
    ; !MODIFIED
            triggerRules(ruleIDsH, 3)
            return
        endIf
    endWhile
EndEvent
 

 

 

-- end edit 3 --

-- edit 4 --

One more thing.. in addCatcher function, again it's a bit hard to be sure when it's not my code, but the part where addCatcher doesn't find existing catcher, and so uses a new one - it finds first index for 'None' to find empty place for new catcher, but I didn't see any place where a new catcher would be added to actorsCatchers array, so added actorsCatchers[pos]=a

 

 

 

    pos = actorsCatchers.find(None)
    if pos==-1
        ; MODIFY ------------------
        debug.trace("## addCatcher - did not find actor, and ALL CATCHERS ARE IN USE, pos = " + pos)
        ; MODIFY ------------------
        return
    endIf
    ; MODIFY ------------------
    debug.trace("## addCatcher - did not find actor, now USING NEW catcher for pos " + pos)
    actorsCatchers[pos]=a
    ; MODIFY ------------------

 

 

 

I think it's starting to work pretty nicely now.  For some reason the health event suppress I added starts out enabled, and I couldn't yet figure it out so disabled it for testings - and events seem to be triggering from event catcher now.  Feels significantly more responsive.  Health rules still feel a bit slow at times though, takes about 7 seconds from triggering to go through check and stop combat... and that's when testing it on new save at qasmoke area against single NPC.  I'd say anything above about 1-2 seconds means it doesn't feel like it reacts to the situation.

 

Also, if they are added to protected aliases, should also have them include the health restoration - or actor may stay in  permanent bleedout and constant abuse.  XD

-- end edit 4 --

Posted

 

 

 

On a sidenote, why do i have to manually activate 99% of the creature races again every time start the mod? Its annoying

 

Try to manually clean up the Scent of Sex Config.json.

 

Delete completely the section "races" : {...}

Save the json file and try.

 

 

there is no such section in the config file...

 

 

Then something is wrong.  Are you using mod organizer, is the config file somewhere with write access?  If you do use MO, did you remember to move the config file away from overwrite folder?

 

The races section at least for me, is right after the 'nudity' and before 'rules'.

 

 

    "nudity" :
    {
        "armorKeywords" : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
        "nakedBody" : 2,
        "nakedCalves" : 2,
        "nakedFeet" : 2,
        "nakedForearms" : 2,
        "nakedHands" : 2,
        "nakedHead" : 2,
        "nakedMinLevel" : 0,
        "nakedPelvis" : 2
    },
    "races" :
    {
        "creatures" :
        {
            "enabled" :
            [
                1,
                0,
                0,
                1,
                1,
                1,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ],
            "races" :
            [
                "Ashhoppers",
                "AtronachFrost",
                "AtronachStorm",
                "Bears",
                "Boars",
                "Centurions",
                "Chart Horses",
                "Chaurus",
                "Chaurusflyers",
                "Chickens",
                "Cows",
                "Deers",
                "Dogpanic",
                "Dogs",
                "Dragons",
                "Draugrs",
                "Falmers",
                "FlameAtronach",
                "Gargoyles",
                "Giants",
                "Goats",
                "Hagravens",
                "Horkers",
                "Horses",
                "Horseses",
                "LargeSpiders",
                "Lurkers",
                "Mammoths",
                "Netches",
                "Rabbits",
                "Rieklings",
                "SabreCats",
                "Seekers",
                "Skeevers",
                "Spiders",
                "Spriggans",
                "SprigganXan",
                "Trolls",
                "VampireLords",
                "Werewolfgal",
                "Werewolfpanic",
                "Werewolves",
                "Wispmothers",
                "Wolfpanic",
                "Wolves"
            ]
        },
        "humans" :
        {
            "enabled" : [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],
            "races" :
            [
                "Argonian",
                "Breton Vampire",
                "Breton",
                "DarkElf",
                "DarkElf Vampire",
                "DarkElfAmbriel",
                "Elder",
                "Elder Vampire",
                "HighElf",
                "HighElf Vampire",
                "IMPERIAL",
                "IMPERIAL Vampire",
                "Khajiit",
                "Khajiit Vampire",
                "Manakin",
                "Nord",
                "Nord Astrid",
                "Nord Vampire",
                "Orc Vampire",
                "Orc",
                "Redguard",
                "Redguard Vampire",
                "WoodElf",
                "WoodElf Vampire"
            ]
        }
    },
    "rules" :
    [
        {
            "animsAndTags" :

 

 

 

 

Im using nexus mod manager. And the config file is in "C:\program files (x86)\steam\steamapps\common\Skyrim\Data\SKSE\Plugins\Scent of Sex"

 

Posted

 

Im using nexus mod manager. And the config file is in "C:\program files (x86)\steam\steamapps\common\Skyrim\Data\SKSE\Plugins\Scent of Sex"

 

 

 

That would be standard place for it so it sounds right, but I don't really know for sure how NMM handles things.

Posted

Really great Mod and awesome documentation. Thank you very much CPU.

 

One or question (feature request?):   In the rules I can defined Source+Target+ a number of either none, one, two or three colaborateurs. The number seems to be fixed, that is if I set it to "2 Colaborators"  there need to be two additional NPCs or the rule wont fire at all. Is it possible to add rule modifiers such as "at least X" or "up to X" colaborators? Or did I perhaps misunderstand the rules ...

Posted

Really great Mod and awesome documentation. Thank you very much CPU.

 

One or question (feature request?):   In the rules I can defined Source+Target+ a number of either none, one, two or three colaborateurs. The number seems to be fixed, that is if I set it to "2 Colaborators"  there need to be two additional NPCs or the rule wont fire at all. Is it possible to add rule modifiers such as "at least X" or "up to X" colaborators? Or did I perhaps misunderstand the rules ...

 

"At least" would make the current definition the "up to".  Would make some rules more practical and interesting, for example a creature rule where you define collaborators as 'same race' and just set it "at least 0" and "up to 3".  Right now I believe you'd need to make 4 separate rules for it, and then I think wouldn't have any way to define things so that the rule with 3 cols would have 'hard preference' over the one with zero - so even if there's 3 available, any of the rules could fire.  In practice I think this would just mean an additional setting that would say the rule can fire even if it only manages to fill # collaborator positions.

 

Another quality I miss on the mod is the ability to give rules a true priority setting instead of just weighed triggering.  To use the above as an example, if I wanted to prioritize triggering a rule with 2 creatures of same race, but if such combination is not available, then trigger another rule that's fine with any single creature.  Or something like... for example, if player goes to bleedout, trigger a rule with enemy npc and companion - but if companion is not available, then trigger a rule with enemy npc and player.

 

This could probably work by keeping the rules internally sorted by priority, and when seeking a rule to trigger, start from highest priority and go down the list.. and stop searching after match is found, as soon as the checker comes across rule that has lower priority (since it knows the rest are no longer relevant).. and reset weighed calculation every time lower priority rule is encountered without finding a match yet.  Without sorting would need an array for weighs I guess.

Posted

 

Really great Mod and awesome documentation. Thank you very much CPU.

 

One or question (feature request?):   In the rules I can defined Source+Target+ a number of either none, one, two or three colaborateurs. The number seems to be fixed, that is if I set it to "2 Colaborators"  there need to be two additional NPCs or the rule wont fire at all. Is it possible to add rule modifiers such as "at least X" or "up to X" colaborators? Or did I perhaps misunderstand the rules ...

 

"At least" would make the current definition the "up to".  Would make some rules more practical and interesting, for example a creature rule where you define collaborators as 'same race' and just set it "at least 0" and "up to 3".  Right now I believe you'd need to make 4 separate rules for it, and then I think wouldn't have any way to define things so that the rule with 3 cols would have 'hard preference' over the one with zero - so even if there's 3 available, any of the rules could fire.  In practice I think this would just mean an additional setting that would say the rule can fire even if it only manages to fill # collaborator positions.

 

Another quality I miss on the mod is the ability to give rules a true priority setting instead of just weighed triggering.  To use the above as an example, if I wanted to prioritize triggering a rule with 2 creatures of same race, but if such combination is not available, then trigger another rule that's fine with any single creature.  Or something like... for example, if player goes to bleedout, trigger a rule with enemy npc and companion - but if companion is not available, then trigger a rule with enemy npc and player.

 

This could probably work by keeping the rules internally sorted by priority, and when seeking a rule to trigger, start from highest priority and go down the list.. and stop searching after match is found, as soon as the checker comes across rule that has lower priority (since it knows the rest are no longer relevant).. and reset weighed calculation every time lower priority rule is encountered without finding a match yet.  Without sorting would need an array for weighs I guess.

 

 

The ability to mark the collaborators as "optional" is something I have in my drawer of idea.

But is quite complex to implement (to be sure you have animations for all variations.)

Maybe one day.

 

About Rule Priority, it is already available (it is available from version 1.0)

You can define it in the Rule Properties.

 

Posted

 

 

The ability to mark the collaborators as "optional" is something I have in my drawer of idea.

But is quite complex to implement (to be sure you have animations for all variations.)

Maybe one day.

 

About Rule Priority, it is already available (it is available from version 1.0)

You can define it in the Rule Properties.

 

 

I.. can only find the priority that defines the frequency of the rule?  What I mean is 'hard priority' that says f.ex. that rule with priority 9 will ALWAYS, without fail, be executed if possible.. and rule with priority 8 will ONLY play if no rule with priority 9 can... and priority 7 will ONLY play if no higher priority rule can play (9 or 8) and so forth.  So the higher priority rules will always get first pick on actors.

 

Technically.. the simplest implementation that comes to mind would be.. when rule is picked, instead of single frequency counter, have array of, say.. int(9) for 9 priority levels, and sum the frequencies into index corresponding to rule priority level.. then loop priorities from top down until you find one with non-zero frequency.. and then loop the matched rules but only handle the ones with the desired highest priority, subtract each frequency value from the int[priority] until it comes to <= 0 and you have the rule to play.

 

That would handle both priorities, and random frequency within same priority level.

 

-- edit --

I think I can see what you mean... if collaborators can be a mixed bunch, say 2 males and 1 female... checking to have anims with +1 male, +2 males, +1 male & +1 female, +1 female.. or +0 females & +0 males.. it could get a bit tricky.  And if it allowed only some of the combinations, that would make rule checking heavier by order of magnitude since all valid combinations would then need to be checked as separate rules.. so that's kind of out.

 

Mmh... with 3 collabs max, with all optional.. that would be 8 combinations.  If 0 = required and 1 = optional.. that would be 3 stacked for loops...

 

 

check_all_combinations(actor target, actor source, actor col1, actor col2, actor col3, int col1req, int col2req, int col3req)
int hascol1 = 1
int hascol2 = 1
int hascol3 = 1
bool all_good = true
if col1
  hascol1 = 0
else
  col1req = 1
endif
if col2
  hascol2 = 0
else
  col2req = 1
endif
if col3
  hascol3 = 0
else
  col3req = 1
endif

for i = hascol1 to col1req
  for j = hascol2 to col2req
    for k = hascol3 to col3req
      if all_good
        actor check1 = null
        actor check2 = null
        actor check3 = null
        if k == 0
          check1 = col3
        endif
        if j == 0
          check2 = check1
          check1 = col2
        endif
        if i == 0
          check3 = check2
          check2 = check1
          check1 = col1
        endif
        all_good = find_animation_for_actors(target, source, check1, check2, check3)
      endif  ; all_good
    next k
  next j
next i
return all_good

 

 

Maybe it wouldn't be terrible.  Still, extra work anyway.

Well... actor wouldn't be 'actor', but rather definition of actor from rule participant.. per gender and humanity I guess.. in case of creature, the creature race.  That would make the code a bit different, but principle is same.  The idea is it's a wrapper that can call a test on all combinations the same way you'd call a test for single possibility.

Posted

 

 

 

The ability to mark the collaborators as "optional" is something I have in my drawer of idea.

But is quite complex to implement (to be sure you have animations for all variations.)

Maybe one day.

 

About Rule Priority, it is already available (it is available from version 1.0)

You can define it in the Rule Properties.

 

 

I.. can only find the priority that defines the frequency of the rule?  What I mean is 'hard priority' that says f.ex. that rule with priority 9 will ALWAYS, without fail, be executed if possible.. and rule with priority 8 will ONLY play if no rule with priority 9 can... and priority 7 will ONLY play if no higher priority rule can play (9 or 8) and so forth.  So the higher priority rules will always get first pick on actors.

 

Technically.. the simplest implementation that comes to mind would be.. when rule is picked, instead of single frequency counter, have array of, say.. int(9) for 9 priority levels, and sum the frequencies into index corresponding to rule priority level.. then loop priorities from top down until you find one with non-zero frequency.. and then loop the matched rules but only handle the ones with the desired highest priority, subtract each frequency value from the int[priority] until it comes to <= 0 and you have the rule to play.

 

That would handle both priorities, and random frequency within same priority level.

 

-- edit --

I think I can see what you mean... if collaborators can be a mixed bunch, say 2 males and 1 female... checking to have anims with +1 male, +2 males, +1 male & +1 female, +1 female.. or +0 females & +0 males.. it could get a bit tricky.  And if it allowed only some of the combinations, that would make rule checking heavier by order of magnitude since all valid combinations would then need to be checked as separate rules.. so that's kind of out.

 

Mmh... with 3 collabs max, with all optional.. that would be 8 combinations.  If 0 = required and 1 = optional.. that would be 3 stacked for loops...

 

 

check_all_combinations(actor target, actor source, actor col1, actor col2, actor col3, int col1req, int col2req, int col3req)
int hascol1 = 1
int hascol2 = 1
int hascol3 = 1
bool all_good = true
if col1
  hascol1 = 0
else
  col1req = 1
endif
if col2
  hascol2 = 0
else
  col2req = 1
endif
if col3
  hascol3 = 0
else
  col3req = 1
endif

for i = hascol1 to col1req
  for j = hascol2 to col2req
    for k = hascol3 to col3req
      if all_good
        actor check1 = null
        actor check2 = null
        actor check3 = null
        if k == 0
          check1 = col3
        endif
        if j == 0
          check2 = check1
          check1 = col2
        endif
        if i == 0
          check3 = check2
          check2 = check1
          check1 = col1
        endif
        all_good = find_animation_for_actors(target, source, check1, check2, check3)
      endif  ; all_good
    next k
  next j
next i
return all_good

 

 

Maybe it wouldn't be terrible.  Still, extra work anyway.

Well... actor wouldn't be 'actor', but rather definition of actor from rule participant.. per gender and humanity I guess.. in case of creature, the creature race.  That would make the code a bit different, but principle is same.  The idea is it's a wrapper that can call a test on all combinations the same way you'd call a test for single possibility.

 

 

About priorities...

 

The current implementation does this:

* the rule checker finds what are the rules that are possible to execute. Rules with no participant or with not starting conditions met are excluded.

* the rule player, gets all the rules and calculate a number based on rule priorities. They are 5 levels of priorities today.

A rule with top priority gets 32 point, the next level gets 16, and down to 1.

Then I just calculate a random number based on the sum of all priority numbers, and I will get the rule in the position randomly calculated.

So higher the priority, higher the probability to be executed.

Posted

Ok, this post has grown way too long and spammy - so I'm putting all of it inside spoiler.. just open it to read it.  :dodgy:

It's about my experimenting with the mod, trying to identify problems with it, and some code changes to suggest possible solutions or features.

 

 



 



 

 

I.. can only find the priority that defines the frequency of the rule?  What I mean is 'hard priority' that says f.ex. that rule with priority 9 will ALWAYS, without fail, be executed if possible.. and rule with priority 8 will ONLY play if no rule with priority 9 can... and priority 7 will ONLY play if no higher priority rule can play (9 or 8) and so forth.  So the higher priority rules will always get first pick on actors.

 

Technically.. the simplest implementation that comes to mind would be.. when rule is picked, instead of single frequency counter, have array of, say.. int(9) for 9 priority levels, and sum the frequencies into index corresponding to rule priority level.. then loop priorities from top down until you find one with non-zero frequency.. and then loop the matched rules but only handle the ones with the desired highest priority, subtract each frequency value from the int[priority] until it comes to <= 0 and you have the rule to play.

 

That would handle both priorities, and random frequency within same priority level.

 

 

About priorities...

 

The current implementation does this:

* the rule checker finds what are the rules that are possible to execute. Rules with no participant or with not starting conditions met are excluded.

* the rule player, gets all the rules and calculate a number based on rule priorities. They are 5 levels of priorities today.

A rule with top priority gets 32 point, the next level gets 16, and down to 1.

Then I just calculate a random number based on the sum of all priority numbers, and I will get the rule in the position randomly calculated.

So higher the priority, higher the probability to be executed.

 

 

Yes, I know, but it doesn't allow real hierarchy for rules.  For example, say I wanted to add the rules:

1) player defeated by creature: target player, source creature, collaborator1 creature (same race), collaborator2 creature (same race)

2) player defeated by creature: target player, source creature, collaborator1 creature (same race)

3) player defeated by creature: target player, source creature

 

..and I wanted to set them up so that if there are 3 creatures available (wolf pack, bunch of skeevers, riekling - whatever creatures ahve gangbang animations), then the rule 1 would always take priority.  If there were only 2 creatures (two wolves for example) then rule 2 would play.. and if there were no multiple creatures with available animation, then rule 3 would play with single creature.

 

I could set them up with different priorities, and in case of 3 creatures the rule 1 would be more LIKELY to play, but not guaranteed.  If rules had 'hard priority', then rule 1 would always be evaluated first, find a match, and play (if there are 3 creatures available that is).

 

--- edit ---

 

I was thinking something like this:

 

 

 

        ; There is space for another scene?
        if ssx.countScenesPlaying() >= ssx.maxNumberOfParallelScenes
            ssx.log("Rule Player: Too many scenes already playing", "notifNextScanIn")
            return
        endIf
        ; MODIFIED -------vvvvvvvvvvvvvv
        int maxPrio = 9999 ; highest priority is lowest number
        int totProb = 0 ; collect probabilities
        int numPossibleRules = 0
        int i = theRulesLen
        if prevRuleID>0
            ; Get all the rule that start after the prev rule
            while i
                i-=1
                ssxRule r = theRules[i]
                if r.inUse==2 && r.startsOn==2 && r.prevRule == prevRuleID
                    int prio = r.probability ; priority - this could be r.priority
                    if prio < maxPrio
                        numPossibleRules = 0
                        maxPrio = prio
                        totProb = 0
                    endIf
                    if prio == maxPrio
                        totProb += Math.pow(2, 4 - r.probability) as Int
                        possibleRules[numPossibleRules]=r
                        numPossibleRules+=1
                    endIf
                endIf
            endWhile
            if ssx.areMenuOpen>0 && ssx.checkMenuOpen()
                localPrevRule=prevRuleID
                RegisterForSingleUpdate(5.0)
                ssx.log("Rule Player: Restarting in 5 seconds because a menu is open", "notifNextScanIn")
                return
            endIf
        else
            ; Get all the rule that can start for the specified mode
            while i
                i-=1
                ssxRule r = theRules[i]
                if r.inUse==2 && r.startsOn!=2
                    int prio = r.probability ; priority - this could be r.priority
                    if prio < maxPrio
                        numPossibleRules = 0
                        maxPrio = prio
                        totProb = 0
                    endIf
                    if prio == maxPrio
                        totProb += Math.pow(2, 4 - r.probability) as Int
                        possibleRules[numPossibleRules]=r
                        numPossibleRules+=1
                    endIf
                endIf
            endWhile
            if ssx.areMenuOpen>0 && ssx.checkMenuOpen()
                if prevRuleID
                    localPrevRule=prevRuleID
                endIf
                RegisterForSingleUpdate(5.0)
                ssx.log("Rule Player: Restarting in 5 seconds because a menu is open", "notifNextScanIn")
                return
            endIf
        endIf
        while ssx.letsWait
            Utility.wait(1.0)
        endWhile

        ; pick randomly a rule
        ssxRule theRule = None
        totProb = Utility.randomInt(1, totProb)
        i = numPossibleRules
        while i > 0 && totProb > 0
            i -= 1
            theRule = possibleRules[i]
            totProb -= Math.pow(2, 4 - theRule.probability) as Int
        endWhile
        ; MODIFIED -------^^^^^^^^^^^^^^^^^

 

 

 

Now higher priority rule will ALWAYS play if possible.  It will still randomize between rules of same priority.  This means I can now make a high priority bleedout rule to trigger for source:human(not follower), target:player and source:creature, target:player.. and then low priority rule source:human(follower), target:player.  The high priority rules will always get executed, but if followers manage to kill off the potential sources before the rule triggers, then the lower priority rule will make the followers still 'rescue' the player from permanent bleedout. (Or perhaps just make it a 'solo act' for recovery).

 

The MCM menu totally confuses me, so I didn't add separate property for priority but instead used the existing probability.  This has the side effect that all rules with same priority have same probability to play.  However if rules had 'priority' property, then using it in the two lines:

                    int prio = r.probability ; priority - this could be r.priority

..would let them be modified separately - so rules with same priority could still have weighed probability of triggering.  I tested this out with a few rules, and it seemed to work as I intended.

 

Could also work as optional feature to play higher priorities first, or randomize... if higherFirst == 0 when randomizing and higherFirst == 1 when playing higher priority always first..

                    int prio = r.probability * higherFirst; higherFirst 0 = randomize all, 1 = higher first

Would also be nice to have (in trigger conditions) an actual "random chance" trigger.  It could be percentage 1-100, and work so that during each scan there's [percentage] chance that the rule will be checked.  So if you set scans to happen every 60 seconds, and give the rule 5% chance, then on average it would be checked once every 20 minutes.  Or it could be more simple to use if it was just 'Try to trigger the rule randomly once every N scans'.

 

By the way, do the collaborator settings work right?  I was first trying to test with multiple rules of different collaborator settings, but I was getting strange things already from rule checker:

 

First, I tried rule with player target, creature source, 2 creature collaborators, with collaborators set to 'same race'.  Spawned three hentai skeevers, but I was getting this:

 

 

 

---------------------------------------------------------------------------------------------------------------------

        

[10/14/2016 - 08:01:44PM] SSX DEBUG: Adding test to 3 skeev pos=0

 Ma=False Fo=False Hu=TRUE Na=TRUE SN=TRUE SS=TRUE AR=TRUE/40 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Silvan

[10/14/2016 - 08:01:45PM] SSX DEBUG: Adding Hentai Skeever to 3 skeev pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/40 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:01:46PM] SSX DEBUG: Adding Hentai Skeever to 3 skeev pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:01:46PM] SSX DEBUG: Adding Hentai Skeever to 3 skeev pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/6 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:01:46PM] SSX DEBUG: Bad rule because 8 - no collaborators - 3 skeev



---------------------------------------------------------------------------------------------------------------------

 

 

 

The checker seemed to try to put ALL of the skeevers into source position.. and then it figured there are no collaborators?

So I changed the rule so it just uses any creatures as collaborators, and it seemed to work at first:

 

 

 

---------------------------------------------------------------------------------------------------------------------


[10/14/2016 - 08:58:38PM] SSX DEBUG: Rule Checker: Trying to fill the rule: 1 skeev 3

[10/14/2016 - 08:58:38PM] SSX DEBUG: Adding test to 1 skeev 3 pos=0

 Ma=False Fo=False Hu=TRUE Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Silvan

[10/14/2016 - 08:58:39PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/43 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:40PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:40PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:41PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=2

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/43 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:42PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=2

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:42PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=2

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:42PM] SSX DEBUG: GOOD rule, it can be filled: 1 skeev 3

[10/14/2016 - 08:58:42PM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player defeat by creature

[10/14/2016 - 08:58:43PM] SSX DEBUG: Actor is bad because bleeding: test pos=0

[10/14/2016 - 08:58:44PM] [CF][Framework] Didn't activate actor ["Hentai Skeever" [HentaiCreaturesActor < (FF001353)>]]; already has effect

[10/14/2016 - 08:58:44PM] SSX DEBUG: Adding Hentai Skeever to Player defeat by creature pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/43 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:44PM] SSX DEBUG: Adding Hentai Skeever to Player defeat by creature pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:44PM] SSX DEBUG: Alias Scanner Maintenance of actors

[10/14/2016 - 08:58:45PM] SSX DEBUG: Adding Hentai Skeever to Player defeat by creature pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:58:45PM] SSX DEBUG: Bad rule because 4 - no targets - Player defeat by creature

[10/14/2016 - 08:58:45PM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player defeat by human

[10/14/2016 - 08:58:46PM] SSX DEBUG: Actors: Hentai Skeever, Hentai Skeever, test, Hentai Skeever

[10/14/2016 - 08:58:46PM] SSX DEBUG: Actor is bad because bleeding: test pos=0

[10/14/2016 - 08:58:46PM] SSX DEBUG: Actor is bad for its humanity: Hentai Skeever pos=1

[10/14/2016 - 08:58:46PM] SSX DEBUG: Actor is bad for its humanity: Hentai Skeever pos=1

[10/14/2016 - 08:58:46PM] SSX DEBUG: Actor is bad for its humanity: Hentai Skeever pos=1

[10/14/2016 - 08:58:46PM] SSX DEBUG: Bad rule because 4 - no targets - Player defeat by human

[10/14/2016 - 08:58:46PM] SSX DEBUG: Rule Player: playing rules

[10/14/2016 - 08:58:47PM] SSX DEBUG: Rule Checker - Rules checking completed. Found 3 valid rules. Restarting in 5 seconds.

[10/14/2016 - 08:58:47PM] SSX: FH 1, MC 3

[10/14/2016 - 08:58:47PM] SSX: Rule: 1 skeev 3 with 4 including test and Hentai Skeever

[10/14/2016 - 08:58:47PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker Hentai Skeever distance=444.141296

[10/14/2016 - 08:58:47PM] SSX: Target: test Source: Hentai Skeever With: Hentai Skeever, Hentai Skeever

[10/14/2016 - 08:58:47PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker test distance=0.000000

[10/14/2016 - 08:58:47PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker Hentai Skeever distance=200.309036

[10/14/2016 - 08:58:47PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker Hentai Skeever distance=306.195801

[10/14/2016 - 08:58:48PM] SSX: Starting scene for rule 1 skeev 3

[10/14/2016 - 08:58:48PM] SSX DEBUG: Scene Manager is going in active state (at least one scene running)



---------------------------------------------------------------------------------------------------------------------

 

 

 

The scene started playing as expected.  However, when I tried the same with only 2 skeevers, I got this:

 

 

 

---------------------------------------------------------------------------------------------------------------------



[10/14/2016 - 08:53:01PM] SSX DEBUG: Rule Checker: Trying to fill the rule: 1 skeev 3

[10/14/2016 - 08:53:01PM] SSX DEBUG: Adding test to 1 skeev 3 pos=0

 Ma=False Fo=False Hu=TRUE Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Silvan

[10/14/2016 - 08:53:02PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:53:03PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:53:03PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=2

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:53:04PM] SSX DEBUG: Alias Scanner Maintenance of actors

[10/14/2016 - 08:53:04PM] SSX DEBUG: Adding Hentai Skeever to 1 skeev 3 pos=2

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:53:04PM] SSX DEBUG: GOOD rule, it can be filled: 1 skeev 3

[10/14/2016 - 08:53:04PM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player defeat by creature

[10/14/2016 - 08:53:05PM] SSX DEBUG: Actors: Hentai Skeever, Hentai Skeever, test

[10/14/2016 - 08:53:05PM] SSX DEBUG: Actor is bad because bleeding: test pos=0

[10/14/2016 - 08:53:06PM] SSX: FH 1, MC 2

[10/14/2016 - 08:53:06PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker test distance=0.000000

[10/14/2016 - 08:53:06PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker Hentai Skeever distance=391.929474

[10/14/2016 - 08:53:06PM] SSX DEBUG: Alias Scan: Passing actor to Rule Checker Hentai Skeever distance=333.172180

[10/14/2016 - 08:53:06PM] SSX DEBUG: Adding Hentai Skeever to Player defeat by creature pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/0 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:53:07PM] SSX DEBUG: Adding Hentai Skeever to Player defeat by creature pos=1

 Ma=TRUE Fo=False Hu=False Na=TRUE SN=TRUE SS=TRUE AR=TRUE/41 he=TRUE/100 st=TRUE/100 ma=TRUE/100 Sle=False Snk=False Wea=False Com=False Ble=False Unc=False race=Skeevers

[10/14/2016 - 08:53:07PM] SSX DEBUG: Bad rule because 4 - no targets - Player defeat by creature

[10/14/2016 - 08:53:07PM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player defeat by human

[10/14/2016 - 08:53:08PM] [CF][Framework] Didn't activate actor ["Hentai Skeever" [HentaiCreaturesActor < (FF00134A)>]]; already has effect

[10/14/2016 - 08:53:08PM] SSX DEBUG: Alias Scanner - Scan completed. Found 3 actors

[10/14/2016 - 08:53:08PM] SSX DEBUG: Actor is bad because bleeding: test pos=0

[10/14/2016 - 08:53:08PM] SSX DEBUG: Actor is bad for its humanity: Hentai Skeever pos=1

[10/14/2016 - 08:53:08PM] SSX DEBUG: Actor is bad for its humanity: Hentai Skeever pos=1

[10/14/2016 - 08:53:09PM] SSX DEBUG: Bad rule because 4 - no targets - Player defeat by human

[10/14/2016 - 08:53:09PM] SSX DEBUG: Rule Player: playing rules

[10/14/2016 - 08:53:09PM] SSX DEBUG: Rule Checker - Rules checking completed. Found 3 valid rules. Restarting in 5 seconds.

[10/14/2016 - 08:53:09PM] SSX: Not possible to find a valid actor for the rule, position=2 rule=1 skeev 3

[10/14/2016 - 08:53:09PM] SSX DEBUG: The second Collaborator cannot be found (All Creatures): 1 skeev 3



---------------------------------------------------------------------------------------------------------------------

 

 

Now the checker was still happy, filling out all three positions with 2 skeevers around... then passed it to rule player.. but rule player of course couldn't fill up all positions, because there were only 2 skeevers.

 

--- edit ---

Did a couple more 'tune-ups'.  First, EventCatcher:

 

 

 

Scriptname ssxEventCatcher extends ReferenceAlias ; V1.3

ssxRunner Property ssx Auto

; MODIFIED
bool suppressHealth = false
; !MODIFIED
Actor lastAggressor
Float lastUndress
bool wasINaked
bool catchBleed
int[] ruleIDsB
bool catchNaked
int[] ruleIDsN
bool catchWeapon
int[] ruleIDsW
bool catchCombat
int[] ruleIDsC
bool catchSleep
int[] ruleIDsS
bool catchHealth
int[] catchHealthLevs ; Level of healt, >=0 then as to be greater, <0 has to be less than
int[] ruleIDsH

Event OnInit()
    ruleIDsB = new int[4]
    ruleIDsN = new int[4]
    ruleIDsW = new int[4]
    ruleIDsC = new int[4]
    ruleIDsS = new int[4]
    ruleIDsH = new int[4]
    catchHealthLevs = new int[4]
    lastUndress = -1.0
    wasINaked=false
endEvent

Event OnUpdate()
; MODIFIED
    suppressHealth=false
; !MODIFIED
EndEvent

Function init(bool bleedout, bool naked, bool weap, bool combat, bool sleep, bool health, int[] BRuleIDs, int[] NRuleIDs, int[] WRuleIDs, int[] CRuleIDs, int[] SRuleIDs, int[] HRuleIDs, int[] healthLevs)
    catchBleed = bleedout
    int i = ruleIDsB.length
    while i
        i-=1
        ruleIDsB[i] = BRuleIDs[i]
    endWhile
    
    catchNaked = naked
    i = ruleIDsN.length
    while i
        i-=1
        ruleIDsN[i] = NRuleIDs[i]
    endWhile
    
    catchWeapon = weap
    i = ruleIDsW.length
    while i
        i-=1
        ruleIDsW[i] = WRuleIDs[i]
    endWhile
    
    catchCombat = combat
    i = ruleIDsC.length
    while i
        i-=1
        ruleIDsC[i] = CRuleIDs[i]
    endWhile
    
    catchSleep = sleep
    i = ruleIDsS.length
    while i
        i-=1
        ruleIDsS[i] = SRuleIDs[i]
    endWhile
    if sleep
        RegisterForSleep()
    else
        UnregisterForSleep()
    endIf
    
    catchHealth = health
    i = ruleIDsH.length
    while i
        i-=1
        ruleIDsH[i] = HRuleIDs[i]
        catchHealthLevs[i] = healthLevs[i]
    endWhile
    
    lastAggressor = None
    lastUndress = -1.0
    wasINaked=false
    suppressHealth=false
    UnregisterForUpdate()
EndFunction

Function clean()
    UnregisterForSleep()
    ruleIDsB = new int[4]
    ruleIDsN = new int[4]
    ruleIDsW = new int[4]
    ruleIDsC = new int[4]
    ruleIDsS = new int[4]
    ruleIDsH = new int[4]
    catchHealthLevs = new int[4]
    lastAggressor = None
    lastUndress = -1.0
    wasINaked=false
; MODIFIED
    suppressHealth=false
    UnregisterForUpdate()
; !MODIFIED
EndFunction


; ((- Events **********************************************************************************************************************************


; aeCombatState: 0=not in combat, 1=in combat, 2=searching
Event OnCombatStateChanged(Actor akTarget, int aeCombatState)
    if catchCombat && aeCombatState!=0
        ssx.updateMe(self.getActorReference(), None)
; MODIFIED ----------------- commented out
;        triggerRules(ruleIDsC, 4)
; MODIFIED ----------------- commented out
    endIf
EndEvent



Event OnSleepStart(float afSleepStartTime, float afDesiredSleepEndTime)
    if catchSleep
        ssx.updateMe(self.getActorReference(), None)
        triggerRules(ruleIDsS, 6)
    endIf
endEvent

Event OnEnterBleedout()
    if catchBleed
        ssx.updateMe(self.getActorReference(), None)
        triggerRules(ruleIDsB, 5)
    endIf
EndEvent

Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
    lastAggressor = akAggressor as Actor
    ; MODIFIED
    if (!catchHealth)
        return
    endIf
    if (suppressHealth)
        return
    endIf
    suppressHealth = true
    registerForSingleUpdate(2.0)
    ; !MODIFIED
    int h = ssx.getHealthLevel(Self.getActorReference())
    int i = 4
    while i
        i-=1
    ; MODIFIED
        int ch = catchHealthLevs[i]
        if (ch<0 && h< -ch) || (ch>0 && h>=ch)
    ; !MODIFIED
            triggerRules(ruleIDsH, 3)
            return
        endIf
    endWhile
EndEvent

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
    if catchNaked
        Actor a = Self.getActorReference()
        float justNow = Utility.GetCurrentRealTime()
        bool amINaked = ssx.isActorNaked(a)
        if justNow-lastUndress < 10.0 || amINaked==wasINaked
            return
        endIf
        wasINaked=amINaked
        lastUndress = justNow
        ssx.updateMe(self.getActorReference(), None)
; MODIFIED ----------------- commented out
;        if ssx.isActorNaked(a)
;            ssx.updateMe(self.getActorReference(), None)
;            triggerRules(ruleIDsN, 2)
;        endIf
; MODIFIED ----------------- commented out
    endIf
EndEvent

Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)
    if catchNaked
        Actor a = Self.getActorReference()
        float justNow = Utility.GetCurrentRealTime()
        bool amINaked = ssx.isActorNaked(a)
        if justNow-lastUndress < 10.0 || amINaked==wasINaked
            return
        endIf
        wasINaked=amINaked
        lastUndress = justNow
        ssx.updateMe(self.getActorReference(), None)
; MODIFIED ----------------- commented out
;        if ssx.isActorNaked(a)
;            ssx.updateMe(self.getActorReference(), None)
;            triggerRules(ruleIDsN, 2)
;        endIf
; MODIFIED ----------------- commented out
    endIf
EndEvent


Function triggerRules(int[] ruleIDs, int catchMode) ; Send the event to play the rule for all registered rule IDs. This will fail because the actor may not be in the rule's participants
    ; catchMode: 0=unspecified (random), 1=player ask (not really an event), 2=nudity, 3=health, 4=combat, 5=bleedout, 6=sleep
    if ruleIDs[0] == 0 && ruleIDs[1] == 0 && ruleIDs[2] == 0 && ruleIDs[3] == 0
    ; if all rules are empty, there's no point calling a mod event
        return
    endIf
    int handle = ModEvent.Create("ssxPlayRule")
    ModEvent.PushForm(handle, Self.getActorReference())
    ModEvent.PushForm(handle, lastAggressor)
    ModEvent.PushInt(handle, catchMode)
    ModEvent.PushInt(handle, ruleIDs[0])
    ModEvent.PushInt(handle, ruleIDs[1])
    ModEvent.PushInt(handle, ruleIDs[2])
    ModEvent.PushInt(handle, ruleIDs[3])
    ModEvent.Send(handle)
EndFunction

; -))

 

 

 

- killed the rule trigger for equip, unequip, combat state

 

Left only ssx.updateMe() calls.  For combat state change it's because I figure there's rarely if ever a need for rules that actually trigger immediately from combat change, and I think of it rather as 'validating' condition - like you build an arousal based rule, but make it trigger only if not in combat.  Starting up combat seemed to give massive mod event spikes with multiple rules that I really didn't need to have checked every time I enter combat.  The equip/unequip was much the same, although I hesiateted with it for a moment.

I'm not sure if these were 'good' changes, but for my own setup I need to cut the mod events as much as possible to make it even marginally playable.  In real gameplay I still get about 15 second delay from going to bleedout, to point where the combat stops - that's early in play session, in outdoors bandit keep so there's not too many actors around.

 

- added condition to evenCatcher to stop mod event calls if all rules are zeroes

 

Even empty event calls with zero rules seemed to take up to 18 or more seconds to go through the event handling, so I'd much rather just snuff those out before creating the event.

 

RuleChecker:

 

 

; The catchers have to be added to all rules, also the ones without valid actors
Function setUpCatchers()
    ; find for all rules the ones that require an event
    ; for each actor, set up a catcher of the appropriate type (depending on the rule requirements, do an exception for the player bleedout)

    ; MODIFIED -------------- was getting some totally strange IDs here
    catchBleedRuleIDs = new int[4]
    catchBleedRuleIDs = new int[4]
    catchWeaponRuleIDs = new int[4]
    catchCombatRuleIDs = new int[4]
    catchSleepRuleIDs = new int[4]
    catchHealthRuleIDs = new int[4]
    catchHealthLevs = new int[4]
    ; MODIFIED -------------- was getting some totally strange IDs here

    int i = ssx.rules.length

 

 

I have no idea why, but I was getting some strange rule id numbers on the catchBleedRuleIDs, and I think on combat rules ids too.  Looking at creation kit, they are initialized to zeroes, and I couldn't find any references to those arrays from the script that would explain it.. but initializing them in setUpCatchers removed the problem.  For bleedout rules in particular, there were 3 trash values in the array, so only 1 real bleedout rule fit in.  Since that was the defeat-by-creature, I wasn't getting the defeat-by-human rule to trigger.  Now it seems to work properly (still with 15 second delay though).

 

--- end edit ---

--- edit 2 ---

Another question... I've noticed several times that when I do manage to get a bleedout scene running, it can often fail on next go.  I was looking at one of the logs, and found message that there are no free slots for scenes.

 

Looking at SceneManager, ssxAnimEnd at the start it assumes the scene is still listed

    int pos = ssx.sceneTCs.find(tc)
    if pos==-1
        return ; No scene found, we cannot really do anything
    endIf
    ssxRule r = ssx.sceneRs[pos]

But I couldn't find anywhere a call to release scene like in the function below it:

Function releaseAllScenes()
    int i=ssx.scenes.length
    while i
        i -= 1
        ssx.releaseScene(None, index=i, a=None)
    endWhile
EndFunction

Are the scenes meant to clear out some other way, or should it be called there?

-- end edit 2 --

-- edit 3 --

...so I went ahead and tried it.  And it seems to work.  I modified the end of the ssxAnimEnd event:

 

 

    i = Positions.length
    pos=-1
    while i
        i -= 1
        Actor a = Positions[i]
        if a
            if pos==-1
                pos=ssx.searchScene(none, -1, a=a)
            endIf
            if pos!=-1 && ssx.sceneRs[pos]
                if ssx.sceneDs[pos]==a
                    ssx.sceneRs[pos].wearAtEnd(ssxRule.targetPosition(), a)
                elseIf ssx.sceneSs[pos]==a
                    ssx.sceneRs[pos].wearAtEnd(ssxRule.sourcePosition(), a)
                elseIf ssx.sceneC1s[pos]==a
                    ssx.sceneRs[pos].wearAtEnd(ssxRule.collaboratorPosition(), a)
                elseIf ssx.sceneC2s[pos]==a
                    ssx.sceneRs[pos].wearAtEnd(ssxRule.collaboratorPosition(), a)
                elseIf ssx.sceneC3s[pos]==a
                    ssx.sceneRs[pos].wearAtEnd(ssxRule.collaboratorPosition(), a)
                endIf
            endIf
            
; MODIFIED
            if r.isStartingOn(ssxRule.getSMBleedOut()) && r.bleedoutMode==1 ; restore health at animation end
                healActor(a)
            endIf
; !MODIFIED
        endIf
    endWhile
    if pos!=-1 && ssx.sceneBs[pos]
        ssx.releaseBed(ssx.sceneBs[pos])
    endIf
; MODIFIED ----------------------- release scene, give a little time to get the f* out of there
; NOTE! this method of combat reset is not entirely 'safe'.  Multiple scenes may be playing
; at once.  Safer way would probably be to first...
    tc.RemoveHook("ScentOfSex")
    if pos != -1
        ssx.releaseScene(None, index=pos, a=None)
    endIf
    Utility.wait(10)
    ; ...check if there are still scenes playing.  If not, then reset combat.
    if ssx.countScenesPlaying() == 0
        ssx.resetCombat()
    endIf
; MODIFIED ----------------------- a little time to get the f* out of there
endEvent

 

 

Added releaseScene to it, also added 10 second pause before reseting combat so you have some time to get out of there.. and added a test to check if there are any other active scenes still playing before actually doing the reset - so all combat is restarted only after all scenes have stopped playing (hopefully at least)

 

( ...amusing thought: increase max scenes to about 10, make universal scene "when someone sees sex", include 'stop all combat'.  If you then initiate sex with someone, in theory it should spread like virus over the area: where ever dragonborn walks, all fighting stops, and sex starts happening.. and it spreads.  XD )

 

I also noticed I was having an issue where the last attacker was removed by alias scanner before sex happened because they wandered out of range.  So I increased the valid range to 6000.0.  This means of course there's more actors to check so startup is slower, but it's also more reliable.  Also added 'is3DLoaded()' test, although I think that was unnecessary.  I was considering it in place of distance check if even 6000 wasn't enough, but 6000 apparently fixed the issue.

 

 

 

----------------------------------------------------------------------------------
        while i
            i-=1
            Actor a = allActors[i]
            if a ; Check if still valid
                float x = a.getDistance(playerRef)
; MODIFIED ------------ increase distance from 2000 to 6000.0, added Is3DLoaded
                if a.isDisabled() || a.IsOnMount() || a.isSwimming() || !a.Is3DLoaded() || x>6000.0
; MODIFIED ------------ increase distance from 2000 to 6000.0, added Is3DLoaded
                    num+=1
                    allActors[i].RemoveFromFaction(ssxScanningFaction)
                    ssx.dbg("Alias Scanner: removing " + a.getDisplayName() + " distance " + x, 4, "CellScanner")
                    ssx.hlg(allActors[i], ssx.notifDebugHighlightBad, "ScanBad")
                    allActors[i]=None
                    numActors-=1
----------------------------------------------------------------------------------
Function tryToAdd(Actor a)
; MODIFIED ------------ increase distance from 3000.0 to 6000.0
    if !a || !ssx.validateActor(a) || !a.getParentCell().IsAttached() || PlayerRef.getDistance(a)>6000.0
        ssx.dbg("Actor " + a.getDisplayName() + " is removed because it is not valid", 4, "CellScanner")
; MODIFIED ------------ increase distance from 3000.0 to 6000.0
        return
    elseIf ssx.needRaces.find(ssx.getRaceID(a.getLeveledActorBase().getRace()))==-1
        ssx.dbg("AliasScan: Actor " + a.getDisplayName() + " is removed because its race is not needed", 4, "CellScanner")
        ssx.hlg(a, ssx.notifDebugHighlightBad, "ScanBad")
        return
----------------------------------------------------------------------------------

 

 

 

One more change I did was to ssxEventCatcher script, OnHit event - I changed it so that lastAggressor is only updated if event actually gets an aggressor - so a random hit from anonymous source won't invalidate the last aggressor.  Not totally sure if that was necessary either, but it should do more good than harm at least.

 

 

 

Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
    ; MODIFIED
    if akAggressor
        lastAggressor = akAggressor as Actor
    endIf
    if (!catchHealth)
        return
    endIf
    if (suppressHealth)
        debug.trace("## SUPPRESSING HEALTH EVENT CALL")
        return
    endIf
    suppressHealth = true
    registerForSingleUpdate(2.0)
    ; !MODIFIED
    int h = ssx.getHealthLevel(Self.getActorReference())
    int i = 4

 

 

 

With all of these changes, I charged into bandit camp and got defeated five times in row - and event started on every single time.. although a couple of times I still saw the event trigger miss (0 valid rules) and the rule played from regular checker instead.  I'm not sure why.. would like it if the event was 100% reliable so regular scanner could be set to run much more slowly.

 

Right now - if I understood it right, even with 'prefered' actors from event catcher, the rulechecker still scans every available actor to fill the rules.  Perhaps it could first do a quick pass through all (up to 4) rules with -only- preferred actors, and if it finds at least one rule that can be triggered, it accepts that, and moves on without doing any further checks.  That could bypass a lot of stuff, and hopefully make it more responsive...

--- end edit 3 ---

 

-- notes --

 

- When setting participants on scene, if you set [X] but does not participate (for example for generic / human), and then change that to 'Specific' actor, the 'does not participate' becomes grayed out, but after you select a specific actor and save the participants, there's an error - and it still shows '1 participant, 1 not participating'.

 

- Using the sexlab 'move scene location' hotkey during scene seems to stop/release the scene, but leaves player permanently in AI control mode, unable to move or act.

 

- I seem to be getting some strange results when I have multiple scenes enabled.  It's as if actors accepted for different scenes were getting mixed with eachother.. like, I have a rule with source 'specific (a follower)' and target 'player', but I got an unrelated vampire thrall NPC filling the source slot - which I think was probably accepted to a different bleedout rule that was attempting to start from event catcher).  Is it possible that the actor arrays get mixed if rule checker is trying to match rules from both regular scanner and event catcher at once?

 

- It seems that player actor keeps accumulating event catchers over time, based on the trace code I added.  I was counting 5 of them firing at one point when getting 'onBleedout' event.. but all except one had zeroes for rule indexes so with the added test to filter out all-zero calls they never got to point of firing a mod event.  They persist through savegames, and the only way I found for removing them was to 'cleansave' and reinstall SSX.  I don't know the cause of this - it's possible it's something in what I changed, and it's possible it's because I keep swapping between codebases I use, but this may be something to keep an eye on anyway.

 

- From time to time player goes into state where going to bleedout affects an instant heal and recovery before any rules have a chance to fire.  It seems to happen even if SSX is not enabled.  I'ts not very common and I haven't been able to pinpoint the cause.  The state persist through saves, and it seemed to persist even through cleansaving, although got reseted soon afterwards - I think it happened either because of second reload after cleansave, or because I did a change on a rule (not directly because of -what- I changed in the rule though).  I know it can be cleared, but I'm not entirely sure how it happens.  It can involve any/all of: cleansave, getting into combat state, getting killed... in some order and combination.  I managed to do it once, then backtracked to save that was still having the issue and tried to replicate it.  Gave up after about two hours.

 

- What happens if there's scene going on that has 'stop all combat' set, and a scanned actor moves out of range and gets removed from AllActors?  It seems that actor might remain in the 'magic friends' faction, and not get removed when the scene ends and combat should reset?

 

I tinkered a bit with alias scanner, tried to make it so that when it maintains the actor list, it also checks the 'friends status' of all tracked actors if the status changes on player.  Also removes actors from friends faction when they get removed from scan AllActors, and sets actors to same status with player when they are added to AllActors.  Could probably also call stop combat, stop alarm and sheathe weapon on them if they get added, but didn't do that:

 

 

 

ReferenceAlias[] Property scanActors Auto

ObjectReference[] Property beds Auto
int Property numBeds Auto
; MODIFIED ------------ player magif friend state, monitor for change and ensure all actors match
bool m = true ; magic friends - this is safest state to assume at first
; MODIFIED ------------ player magif friend state, monitor for change and ensure all actors match
; -))
 
-----------------------------------------------------------------------------------
 
    Event OnUpdate()
        ssxAS.stop()
        Utility.wait(0.3)
        ssxAS.start()
        if ssx.iAmActive==0
            ssxAS.stop()
            ssxAS.reset()
            return
        endIf
        start()
        ssx.dbg("Alias Scanner Maintenance of actors", 3, "CellScanner")
        Utility.wait(0.5)

        while ssx.letsWait
            Utility.wait(1.0)
        endWhile

        int times = 0
        while busyUpdating>0
            Utility.wait(0.1)
            times+=1
            if times>50
                ssx.dbg("Impossible to update the actors... " + busyUpdating, 3, "CellScanner")
                busyUpdating=0
            endIf
        endWhile
        busyUpdating+=1
        if ssx.iAmActive==0
            ssxAS.stop()
            ssxAS.reset()
            return
        endIf
        
        ssx.playerSex = 0
        if (ssx.genderMode==0 && PlayerRef.getLeveledActorBase().getSex()) || (ssx.genderMode!=0 && Math.LogicalAnd(SexLab.getGender(PlayerRef), 1))
            ssx.playerSex = 1
        endIf

        int i = scanActors.length
        while i
            i-=1
            Actor a = scanActors[i].getActorRef()
            if a && allActors.find(a)==-1
                if !a.IsInFaction(ssxScanningFaction)
                    a.addToFaction(ssxScanningFaction)
; MODIFIED ------------- new actors must follow the rules
                    if m && !a.IsInFaction(ssx.ssxAllFriends)
                        a.addToFaction(ssx.ssxAllFriends)
                    elseIf !m && a.IsInFaction(ssx.ssxAllFriends)
                        a.RemoveFromFaction(ssx.ssxAllFriends)
                    endIf
; MODIFIED ------------- new actors must follow the rules
                endIf
                if numActors<allActors.length
                    tryToAdd(a)
                endIf
            endIf
            if ssx.iAmActive==0
                ssxAS.stop()
                ssxAS.reset()
                return
            endIf
            while ssx.letsWait
                Utility.wait(1.0)
            endWhile
        endWhile
        
        int num = 0
        i = allActors.length
; MODIFIED ------------- get player friend status and prepare to update on actors if needed
        bool f = PlayerRef.IsInFaction(ssx.ssxAllFriends)
        if f != m
            m = f ; player friend state changed, update m to hold current value...
            f = true ; ...and use f to inform that everyone must follow
        else
            f = false ; player friend state has not changed, no need for updates
        endIf
; MODIFIED ------------- get player friend status and prepare to update on actors if needed
        while i
            i-=1
            Actor a = allActors[i]
            if a ; Check if still valid
; MODIFIED ------------ increase distance from 2000 to 6000.0, added Is3DLoaded
                float x = a.getDistance(playerRef)
                if a.isDisabled() || a.IsOnMount() || a.isSwimming() || !a.Is3DLoaded() || x>6000.0
; MODIFIED ------------ increase distance from 2000 to 6000.0, added Is3DLoaded
                    num+=1
                    allActors[i].RemoveFromFaction(ssxScanningFaction)
; MODIFIED -------------- remove from magic friends faction too
                    if a.IsInFaction(ssx.ssxAllFriends)
                        allActors[i].removeFromFaction(ssx.ssxAllFriends)
                    endIf
; MODIFIED -------------- remove from magic friends faction too
                    ssx.dbg("Alias Scanner: removing " + a.getDisplayName(), 4, "CellScanner")
                    ssx.hlg(allActors[i], ssx.notifDebugHighlightBad, "ScanBad")
                    allActors[i]=None
                    numActors-=1
                    if numActors<0
                        numActors=0
                    endIf
                elseIf a.isDead()
                    num+=1
                    ; Not removing the faction because it will not be good anymore
; MODIFIED -------------- remove from magic friends faction though.  No remorse!
                    if a.IsInFaction(ssx.ssxAllFriends)
                        a.removeFromFaction(ssx.ssxAllFriends)
                    endIf
; MODIFIED -------------- remove from magic friends faction though.  No remorse!
                    ssx.dbg("Alias Scanner: removing forever " + a.getDisplayName(), 4, "CellScanner")
                    ssx.hlg(allActors[i], ssx.notifDebugHighlightBad, "ScanBad")
                    allActors[i]=None
                    numActors-=1
                    if numActors<0
                        numActors=0
                    endIf
; MODIFIED -------------- if player magic friend status changed, all must follow
                elseIf f ; friends status has changed
                    if !m && a.IsInFaction(ssx.ssxAllFriends) ; we are no longer magic friends!
                        a.removeFromFaction(ssx.ssxAllFriends)
                    elseIf m && !a.IsInFaction(ssx.ssxAllFriends) ; everyone must become magic friends!
                        a.addToFaction(ssx.ssxAllFriends)
                    endIf
                endIf
; MODIFIED -------------- if player magic friend status changed, all must follow
            endIf
            if ssx.iAmActive==0
                ssxAS.stop()
                ssxAS.reset()
                return
            endIf
            while ssx.letsWait
                Utility.wait(1.0)
            endWhile
        endWhile
        if num
            ssx.dbg("Alias Scanner: removed " + num + " no more valid actors", 3, "CellScanner")
        endIf

 

 

 

Current changes I'm using in-game (using alias scanner), they are based on 1.3G version:

SSX_changes.zip

I've also removed the 'scanner faction' requirement from alias scanner aliases, and increased the number of scan aliases to 32 (had to clean-save to make the quest changes work) - so far it's worked fine for me.  The .esp isn't in the zip though because I don't want to cause any confusion with it.

 

Just to be clear: the zip is not intended as patch or 'next version', I'm posting this because seeing the changes in their context in the code gives much better idea about what I did - and so I'm only posting source code, not compiled scripts.  I've stripped most of the debug trace I had added, and hopefully remembered to mark every change with 'MODIFIED' comment.

 

Also fair warning: these use ssxRunner.psc, which in turn requires ski_main.psc to compile - which I couldn't find anywhere (it wasn't in the skyui dev pack I downloaded)... which means in my own version I had to make dummy ski_main and strip version check away from ssxRunner.  Those are not 'good changes', so didn't post them in the zip - which in turn means the source in zip won't compile 'as is'.

 

--- another edit ---

I was also trying to change RuleChecker so it would scan event rules first using only preferred and specific actors.  It sort of worked, but didn't seem to make things any faster - and I was still getting all sorts of scans firing left and right, so I concluded I probably just don't understand the mod well enough to attempt something on that kind of scale.

 

I did notice a couple of thingsin the original code though:

 

- The tryToFillTheRule function uses preferred actors ONLY to pass them to FilterActors function... and FilterActors function doesn't use them at all - so essentially they are not used anywhere?

 

- Actor[] dstActors, Actor[] srcActors, Actor[] collActors are all global variables in RuleChecker, so perhaps that's what led to mixup of actors between different rules that I was seeing.

 

Anyway, for the sake of completeness here's the somewhat unsuccessful attempt I made (technically working but unhelpful in practice):

(NOTE: original pasted code had indexing error that broke rules with specific actor type, fixed it in the zipped version, although it still doesn't make it particularly useful)

ssxRuleChecker.zip

 

-- another edit --

I posted earlier "From time to time player goes into state where going to bleedout affects an instant heal and recovery".  I got couple more instanes of this (and just went to earlier save), and they both seemed to happen when NPC defeated player, and was then subsequently killed by companion before the scene would fire.  I think I saw a 'starting a scene with', but never got to animation - I'm not sure though.  Overall it's difficult to track, but I was wondering whether it could somehow be about scenes getting permanently reserved by actors that are no longer valid for actually running the animations.

 

With that thought, I did some changes to alias scanner to have it run some additional sanity checks, and to release scenes under some conditions.  I've been running it with a few hours and so far haven't gotten that problem to manifest again - but can't say anything certain.  I moved the 'removeActor' from allActors into it's own function that also removes the actor from scanning and friends factions, as well as releases a scene in case the actor was involved in it.  Also added a test in maintenance loop that checks the actor with SexLab.ValidateActor, and releases scene with that actor if result is NOT either -10 (actor is animating) or 1 (actor is valid).  This is probably redundant because further checks already check for disabled, onmount, dead etc. and remove the actor in those conditions - which now already release the scene as well.. but I left it in with debug.notification anyway, so I'll see if it catches something.

 

Here's the zip:

ssxAliasScan.zip

 

-- another edit --

Didn't work, and it was a silly thought anyway - stopping and restarting should have cleared any lingering scenes anyway, and at the least a cleansave would.  I'm again at the same point - getting the insta-recoveries without the scenes, and really have no idea what can cause it - or how to fix it.

I'm inclined to believe that it has nothing direct to do with SSX though.  It seems to happen randomly, and when it does it persist through saves - any bleedout results in instant recovery, but without essential/protected status you'll still die normally.  Correction to previous - apparently even with SSX stopped, I still won't die, but rather get the instant recovery.  Sometimes it seems to resolve randomly as well.  I'm sure something causes it, but I haven't got a clue what it is.

--

I'm not sure about this, but I think at least three times it's been result of dying from poison, and at least twice against chaurus warrior which I don't have an animation associated with.  And also at least twice (can't remember other times) I've gotten the 'death' ragdoll animation instead of the bleedout animation, even though essential status has kept me from actually 'dying' - and I have low priority 'backup' animation that kicks in from bleedout status without source.  The latest occasion I got into this mess, I was 'killed' to ragdoll animation by poison from chaurus warrior, then after a while the solo animation kicked in and brought me back alive.. and after that every defeat gives the insta-recovery.

- maybe it does have something to do with not being able to start animation (because no valid animation or no valid participants)

- maybe death from poison or other 'over time' effect is handled differently and messes up things

- maybe the over time effect keeps hitting even in bleedout mode, and that screws up something

- maybe, since I was wrong about dying when SSX is stopped, it could have something to do with a lingering quest alias anyway

- I know the recovery doesn't come from SSX 'quick heal' or 'restore health and limbs' since I put a trace on those calls and it didn't trigger

Maybe it's something else entirely, duh.

-- edit --

Progress!

It seems it does have something to do with scenes getting stuck afterall.  I'm still not sure what causes it, but it seems I can clear the state by simply initiating a SexLab scene (I'm using matchmaker to do it, just activating it for player alone is enough).  I'm also seeing actors staying in friendly faction after scene, and since I'd added a test to not reset combat if there's still a scene ongoing, I'm suspecting there may be a scene stuck in SSX.  Other than that, it's possible actors are getting stuck in SL animating faction (possibly player), and forcing a scene runs the actor through SexLab.ValidateActor which in turn would clear the faction if actor is no longer in active SL thread.  I was already passing AllActors through sexlab's ValidateActor on each alias scan maintenance, but that doesn't include player I think.  I need to run player through the check too and see if that clears things up.

-- another edit --

I was trying to track down some issues in playing rules from event catcher (actually was trying to integrate an instant 'stop combat' to some events), and came across this part in ssxRulePlayer:

        if r1==0 && r2==0 && r3==0 && r4==0
            ; Find a rule by calling the Rule Checker
            ssx.log("Rule Player: No rules found from the catcher, asking Rule Checker.", "notifError")
            int handle = ModEvent.Create("ssxStartSSXRC")
            ModEvent.PushInt(handle, 0)
            ModEvent.Send(handle)
            return
        endIf

Does this do what it's intended to do?  I believe rule checker is the only script that catches this event, and there it just ensures the checker is in active mode - and most of the time does nothing.  Would it work better to call the ssxDoIt event with "RuleChecker" as parameter to force immediate check for rules? (Although if rule checker is in inactive state, it would also require start event to actually activate.. on the other hand not sure it should?)

-- another edit --

I experimented with something different.  In the eventCatcher, when triggering events on mode 5 or 3 (bleedout or health rule), when eventCatcher is attached to player character, and when at least one rule has non-zero ID, I placed an immediate call to stop combat.  Then later in rule checker when the actual rules are tested, I placed a reset combat on each return path if it doesn't result on a scene.  The results were pretty good - combat stopped instantly, fast enough for even the health rules to take effect.

 

Also tuned the alias scanner's actor maintenance a bit - I was testing player's 'magic friends' status too late on the onUpdate, so moved it earlier.  Also moved some things out on their own function so instead of placing an actor into friends faction can call 'stop combat' on single actor to also actually stop combat.

 

There was still an issue with the combat management however.  Actor scanner only adds actors that are actually 'needed' into AllActors, but this means actors that are not directly potential participants on rules won't have their combat stopped/restored when rules trigger.  I moved the maintenance code around so that it manages the combat/friends faction of all the actors it scans, and technically it works like that - but in practice it's far too slow to respond in need.  Probably this would need a separate scan for actors that are close to player but not in magic friends faction.. and then stopping combat for them separately.  This could perhaps be handled by separate alias that was activated on stopping combat, and then reversed when combat should start again (walking through references and activating combat on them unless they are in allActors).

 

Overall I was pretty happy with the results - but the code is starting to get a bit messy.. and it's not perfect.  For example it's stopping combat on all health/bleedout rules, regardless of whether the triggered rules actually state that combat should stop.

 

 

Posted

Suggestion for the dialogue after/before sex scene. Random. I know atleast for after sex scene,random would probably have to exclude "my arse is sore now" but i think all the other one would fit nice. Im having good sucess so far, havent tried any animal stuff. And suggestion for locations. How about an option for Hostile locations combined exp: dungeons,bandit camps.. And non-hostile locations like inns,towns,cities,holds ect ect. Thanks a million CPU

Posted

Suggestion for the dialogue after/before sex scene. Random. I know atleast for after sex scene,random would probably have to exclude "my arse is sore now" but i think all the other one would fit nice. Im having good sucess so far, havent tried any animal stuff. And suggestion for locations. How about an option for Hostile locations combined exp: dungeons,bandit camps.. And non-hostile locations like inns,towns,cities,holds ect ect. Thanks a million CPU

 

Seconded, though I'd also be happy with instructions on how to add our own lines. (I do have some CK experience, but I've never tried to do dialogue before.)

Posted

Hi. Thanks for the mod. It works much better since 1.3.

I'm still confused by some rules setup though. I tried to use the "same race" for collaborators to make rules with multiple creatures but this didn't work.

Here is what I got in the log for 4 rieklings:

	Line 12028: [10/17/2016 - 08:29:49PM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player submits to 4 creatures
	Line 12257: [10/17/2016 - 08:29:49PM] SSX DEBUG: Adding Tatjana to Player submits to 4 creatures pos=0
	Line 12495: [10/17/2016 - 08:29:50PM] SSX DEBUG: Adding Riekling Hunter to Player submits to 4 creatures pos=1
	Line 12689: [10/17/2016 - 08:29:51PM] SSX DEBUG: Adding riekling to Player submits to 4 creatures pos=1
	Line 12895: [10/17/2016 - 08:29:51PM] SSX DEBUG: Adding Riekling Warrior to Player submits to 4 creatures pos=1
	Line 13089: [10/17/2016 - 08:29:52PM] SSX DEBUG: Adding Riekling Warrior to Player submits to 4 creatures pos=1
	Line 13103: [10/17/2016 - 08:29:52PM] SSX DEBUG: Bad rule because 8 - no collaborators - Player submits to 4 creatures

I changed then the collaborator to be a generic male creature (with some race filtering) and it worked ok.

So I'm wondering if "same race" really does what I think it does.

Posted

Hi. Thanks for the mod. It works much better since 1.3.

I'm still confused by some rules setup though. I tried to use the "same race" for collaborators to make rules with multiple creatures but this didn't work.

Here is what I got in the log for 4 rieklings:

 

 

	Line 12028: [10/17/2016 - 08:29:49PM] SSX DEBUG: Rule Checker: Trying to fill the rule: Player submits to 4 creatures
	Line 12257: [10/17/2016 - 08:29:49PM] SSX DEBUG: Adding Tatjana to Player submits to 4 creatures pos=0
	Line 12495: [10/17/2016 - 08:29:50PM] SSX DEBUG: Adding Riekling Hunter to Player submits to 4 creatures pos=1
	Line 12689: [10/17/2016 - 08:29:51PM] SSX DEBUG: Adding riekling to Player submits to 4 creatures pos=1
	Line 12895: [10/17/2016 - 08:29:51PM] SSX DEBUG: Adding Riekling Warrior to Player submits to 4 creatures pos=1
	Line 13089: [10/17/2016 - 08:29:52PM] SSX DEBUG: Adding Riekling Warrior to Player submits to 4 creatures pos=1
	Line 13103: [10/17/2016 - 08:29:52PM] SSX DEBUG: Bad rule because 8 - no collaborators - Player submits to 4 creatures

 

 

I changed then the collaborator to be a generic male creature (with some race filtering) and it worked ok.

So I'm wondering if "same race" really does what I think it does.

 

No, collaborators seem to be somewhat broken.  Posted the same thing in that huge writing a couple posts earlier - it seems like it tries to put all of the creatures to source position, and then complains that there are no collaborators.  Even if I changed it to 'general creatures', it broke in a different way - the rule would work if there are right number of them, but it'll match the rule even if there are less creatures than it needs - which means it'll interfere with any other creature rules, and basically randomly make them not work.

 

At this point this is just a guess since I haven't really looked at how the code works at that part, but thinking about it it seems like it doesn't carry the source correctly to the test.  if it thinks the source is empty, that would explain why it can't match the 'same race', and would also explain the way it behaved with 'generic creature' - that is, it wouldn't know that one is already reserved as source.

Posted

Ok , so i narrowed down all my problems with scent to 1 function. Actor scanning. I have long instaces of no rules starting in my game, even in crowded areas with rules set on "random" and start right away with 30 second timers. Then i noticed something wierd. The actors detected by scent did not match the real number of actors in a cell. I could be in room with 1 female and 1 guy and scent will say "1MC, 4FH, 5MH" or soemthing like that. If the actors and scent detection did not match then the rules would not play. It takes scent sometimes up to 5 minutes to catch up with the cell. As an aleternative i can switch it off and on and change scanning method then it will catch up. Untill i change the cell that is. Then the scan is sloging behind my character again,  usually never catching up = no rules. I tested all scanning methods and even the cloak does not solve the issue. Thats why i had actors running behind me from other cells. Scent assumed i was still in that cell when it did its scan even tho i was far away.

Posted

Hi CPU and everyone interested :)

 

I've been doing some soak testing with the latest files (1.3g) and can report some success with a few suggested minor tweaks to the code  ;)  These alterations, address the following issues.

 

  1. scenes/rules run regardless of the start conditions set for health, stamina or magicka.
  2. actors are included in scenes when they are very far away (e.g I've had an actor travel from Whiterun to Riverwood to be part of a scene).
  3. scenes stop running after playing for a while and then nothing.

 

1. starting conditions for health, stamina and magicka

 

Test conditions: I have two rules that work together. The effects of one rule running will trigger the other rule. I use SexLabUtil1 by Fotogen

 

(link - http://www.loverslab.com/files/file/236-sexlabutil1-2015-03-28/) to enable the effects.

 

'Succubus' rule will harm to the point of death the victim of a sexual attack using a certain type of sex. This will leave the victims health depleted that will in turn trigger the second rule 'Just Do it!', that will replenish the victims health. This was not working, as the second rule would run regardless of the conditions set. I know that 'Arousal' works correctly and so it was just a matter to track down where in the code these conditions were checked.

 

ssxRuleChecker.psc - LInes 1026 to 1060

			if isGood && ssx.weHaveSLA() ; Arousal
				mode = r.getPositionStartMode(ssxRule.getSMArousal(), pos)
				if (mode==1 && ar<r.arousalLevel) || (mode==2 && ar>=r.arousalLevel) 
					ssx.dbg("Actor is bad because arousal: " + a.getDisplayName() + " Level=" + ar + " pos=" + pos, 7, "RuleChecker")
					isGood = false
				endIf
				isAR = isGood
			endIf
		
			if isGood ; Health
				mode = r.getPositionStartMode(ssxRule.getSMHealth(), pos)
				if (mode==1 && he>=r.healthLevel) || (mode==2 && he<r.healthLevel) 
					ssx.dbg("Actor is bad because health: " + a.getDisplayName() + " Level=" + he + " pos=" + pos, 7, "RuleChecker")
					isGood = false
				endIf
				isHE = isGood
			endIf
		
			if isGood ; Stamina
				mode = r.getPositionStartMode(ssxRule.getSMStamina(), pos)
				if (mode==1 && st>=r.staminaLevel) || (mode==2 && st<r.staminaLevel) 
					ssx.dbg("Actor is bad because stamina: " + a.getDisplayName() + " Level=" + st + " pos=" + pos, 7, "RuleChecker")
					isGood = false
				endIf
				isST = isGood
			endIf
		
			if isGood ; Magicka
				mode = r.getPositionStartMode(ssxRule.getSMMagicka(), pos)
				if (mode==1 && ma>=r.magickaLevel) || (mode==2 && ma<r.magickaLevel)
					ssx.dbg("Actor is bad because magicka: " + a.getDisplayName() + " Level=" + ma + " pos=" + pos, 7, "RuleChecker")
					isGood = false
				endIf
				isMA = isGood
			endIf

You'll see that the condtions are set for two modes, depending on the start conditions set in the rules.

 

            ; 0 Ignored (position not to check), 1 Has to (or great than), 2 Has not (or less than)
 

Now modes 1 and 2 work correctly for arousal, but I noted that the code logic was different for health, stamina and magicka. I decided to change the logic to match and I was pleased to find that the conditions set in the rules now behave as expected.

 

I also checked out rule conditions where actors are sneaking, have weapons drawn; by having the 'tgt' or 'src' set to 'no' prevents the rules from running.

 

 

2. Although there are already a couple of checks in the code for actor distance from the player, I was still seeing actors showing up in the log that should never be there.

[10/20/2016 - 10:37:55AM] SSX DEBUG: Cell Scan: Passing actor to Rule Checker Alvor distance=900.959106
[10/20/2016 - 10:37:55AM] SSX DEBUG: Cell Scan: Passing actor to Rule Checker Orgnar distance=38.671139
[10/20/2016 - 10:37:55AM] SSX DEBUG: Cell Scan: Passing actor to Rule Checker Gaia distance=0.000000
[10/20/2016 - 10:37:55AM] SSX DEBUG: Cell Scan: Passing actor to Rule Checker Hod distance=340282346638528860000000000000000000000.000000
[10/20/2016 - 10:37:55AM] SSX DEBUG: Cell Scan: Passing actor to Rule Checker Sven distance=917.849976
[10/20/2016 - 10:37:56AM] SSX DEBUG: Cell Scan: Passing actor to Rule Checker Embry distance=546.424438

Clearly Hod should never be considered for a scene. However occasionally you will get actors travelling vast distances to take part in a scene even though the option is set in the MCM to stop scenes that exceed the timeout periods. While you're waiting, nothing else appears to happen. I decided to include a couple more checks and these appear to reduce if not stop the global treks, allowing actors only in the locale to be considered for scenes.

 

ssxCellScanner.psc Lines 150 to 159. Condtion added HERE @ 153, 156 & 157

		while i
			i-=1
			Actor a = ssx.allActors[i]
			if a && PlayerRef.getDistance(a) < 3000 <--- HERE
				ssx.dbg("Cell Scan: Passing actor to Rule Checker " + a.getDisplayName() + " distance=" + a.getDistance(PlayerRef), 3, "CellScanner")
				ssx.hlg(a, ssx.notifDebugHighlightGood, "ScanGood")
			elseif a  <--- HERE
				ssx.allActors[i] = None    <--- HERE
			endIf
		endWhile

and HERE @ 6422, in ssxRunner.psc Lines 6420 to 6429

		while i
			i-=1
			if src[i] && PlayerRef.getDistance(src[i]) < 3000 <--- HERE
				allActors[allActorsNum] = src[i]
				allActorsNum+=1
				if check && src[i].isInFaction(ssxInvolved)
					src[i].removeFromFaction(ssxInvolved)
				endIf
			endIf
		endWhile

Scenes now occur far more frequently and this also appears to address issue 3 where things seem to grind to a halt.

 

General Info:

 

I have noticed that although rule condition filters are set and acknowledged in the log, occasionally rules do run regardless. If you find this annoying you can change the rule priority (in rule properties) to a lower setting to discourage the rules from running. I have my rule Just Do It! set to very low.

 

I was getting a lot of CTD and Run-Time (R6025) errors during animations. I was at a loss to know what was causing this. To proved it wasn't Scent of Sex I tried an alternative - Random Sex Mod for SexLab by Arizona Steve (link - http://www.loverslab.com/files/file/395-random-sex-mod-for-sexlab-2016-09-17/ ), and it still occurred. I'm currently use SexLab 1.62 and I did recently update my PapyrusUtils to 3.3. I decided to remove this and the problems appear to have gone away. I'm not saying that the code in 3.3 is faulty, but it maybe more compatible with the upcoming SexLab 1.63.

 

As always I include my rules and the very large log (caused mainly by MHIYH throwing a wobbler with ownership of a horse). But the log proves that scenes run well (6 hour play) with both human and creature animations.

 

Hope this helps

Rules & Log.7z

Posted

Hi CPU and everyone interested :)

 

I've been doing some soak testing with the latest files (1.3g) and can report some success with a few suggested minor tweaks to the code  ;)  These alterations, address the following issues.

 

  1. scenes/rules run regardless of the start conditions set for health, stamina or magicka.
  2. actors are included in scenes when they are very far away (e.g I've had an actor travel from Whiterun to Riverwood to be part of a scene).
  3. scenes stop running after playing for a while and then nothing.

1) Can confirm the same issue and fix, the health / stamina / magicka rules were working opposite to what they were supposed to until changed those lines (part of the mega-post #564)

2) I haven't generally seen this in that kind of magnitude, but sometimes I've had an actor get 'stuck' into playing the same scene over and over - regardless of the distance, which might be symptom of same issue.

3) Here too I was seeing the same issue until some of the changes I've done past few weeks - at current state they seem to have stopped - although it can still get locked up if a scene fails to start after being triggered (this too mostly in post #564)

 

Overall, I think there's a few potential causes behind 2 and 3

- the scene checking often takes a long time, which can sometimes cause scenes to fire "when the moment has passed"

- actors are removed from AllActors list, but not all factions are properly handled, so they can get stuck 'out of sync' with factions

- sometimes actor wanders out of range between triggering scene and actually starting the scene, so they are no longer available when scene should start

- it seems sometimes sexlab scenes are not properly cleaned up, which I think can break the whole mod (scenes no longer play)

 

I've tried to include various sanity checks to alias scanner, which in many cases can recover if factions get messed up, but one thing they still can't handle (I think) is the situation where sexlab scene isn't cleaned up right.  However that one seems to clear up by starting a scene with some other program (like matchmaker).  Would still be nice to be able to handle it automatically within SSX.  I think it originally happens when scene fails to play - but haven't been able to pinpoint the exact issue in the code.

 

Using the same SL 1.62 and papyrus 3.3, CTDs are practiclaly nonexistent for me except at initial loading of game - and I can work around those by setting CPU affinity to single core until the game has finished loading.  I had one 'pure virtual call' crash when animation was starting, I think it was conneted to item that auto-unequiped itself under some conditions.. after setting that item 'never strip' in sexlab, haven't had crashes on scenes.

--- edit ---

There's a bunch of stuff I've tinkered with, which I've posted at post #564 and then later #556 - have a look if you're interested.  I'm playing with alias scanner, so all the changes to scanner that I've made have been for that.. and like I noted in one of the posts, I changed the alias scanner in SCK so it scans all actors without ruling out those that are already in scanned faction (required doing 'cleansave' to get the new quest running).  The changes -should- work without that change too though.

 

Here's zip of the source code with all the changes (I think) that I've made - including the latest one that basically makes the combat stopping on health and bleedout rules instant against player.  It works pretty well I think, except for a few issues:

 

- it stops combat on ALL health and bleedout rules against player, even if rule doesn't set 'stop combat'

- the actual processing of rules is still pretty slow even if combat stops fast.. sometimes means health recovers above health-rule limit before rules actually starts playing, which can fail a scene

- a failed scene start can still lock the mod into bugged state, but it should recover if you force a SL scene to play (generally for player character)

 

I added some extra trace code to 'notification' area (left upper screen).  It's enabled if in debug options you set TRACE for the 'mod started/stopped' option (either just trace or both notify and trace).  A bit counterintuitive to use trace setting for notify, but it worked best for me that way.

changes_13g.zip

Posted

Hi.

I am working right now to fix all problems reported (and in some case fixed) by you guys.

 

The thinks I am doing/are done:

  • (in progress) Add the cells checking to be inclusive or exclusive, like races
  • (testing) Added Factions editor
  • (fixed) NPCs too far away are not ignored (satanfist)
  • (fixed) Fixed the checkings of Health, Magicka, and Stamina (satanfist)
  • (fixed) Improved the event handling to avoid to catch too many events for OnHit and similar events (reikiri)
  • (in progress) Improve the SexLab sexuality preferences in filling actors
  • (new) Setting the collaborator to something that is not NOBODY needs to update the numOfCollbs if it is 0
  • (fixed) Same race, bad rule because no collaborators (never initialized the array in this case)
  • (in progress) Improve the clean up to clean up everything, including SexLab references, properties, arrays, etc.
  • (fixed) Better management of empty arrays in case SexLab creatures are disabled (was not a problem on Nexus version)
  • (new) Split the Items loader and the Actors loader to improve performance
  • (fixed) Better handling of the valid races array in case the actors are not yet scanned
Feel free to send me all changes/patches you did 
Posted

 

Hi.

I am working right now to fix all problems reported (and in some case fixed) by you guys.

 

The thinks I am doing/are done:

  • (in progress) Add the cells checking to be inclusive or exclusive, like races
  • (testing) Added Factions editor
  • (fixed) NPCs too far away are not ignored (satanfist)
  • (fixed) Fixed the checkings of Health, Magicka, and Stamina (satanfist)
  • (fixed) Improved the event handling to avoid to catch too many events for OnHit and similar events (reikiri)
  • (in progress) Improve the SexLab sexuality preferences in filling actors
  • (new) Setting the collaborator to something that is not NOBODY needs to update the numOfCollbs if it is 0
  • (fixed) Same race, bad rule because no collaborators (never initialized the array in this case)
  • (in progress) Improve the clean up to clean up everything, including SexLab references, properties, arrays, etc.
  • (fixed) Better management of empty arrays in case SexLab creatures are disabled (was not a problem on Nexus version)
  • (new) Split the Items loader and the Actors loader to improve performance
  • (fixed) Better handling of the valid races array in case the actors are not yet scanned
Feel free to send me all changes/patches you did 

 

Nice :)  There's a bunch of stuff in post #564, it was just getting so long I put it all inside one big spoiler.  Or most of it could be what you meant by 'improve the clean up to clean up everything'.  Anyway, posted the latest changes on the post right above yours - although it does include a lot of stuff that's more like 'extra features' than straight up 'fixes'.  But it does include everything I've changed in what I'm using in-game.. and all changes should be marked with 'MODIFY' or 'MODIFIED'.

 

The biggest issues that I can think of were..

- scenes sometimes stop playing of player actor going into bugged state, which I think is symptom of the sexlab references not cleaning up

- factions getting messed up, I think in large part because actors moving out of range, or otherwise not getting handled consistently

- handling of combat stop and restart (too slow especially for health rules, and not affecting actors that are not in AllActors)

 

Posted

 

Nice :)  There's a bunch of stuff in post #564, it was just getting so long I put it all inside one big spoiler.  Or most of it could be what you meant by 'improve the clean up to clean up everything'.  Anyway, posted the latest changes on the post right above yours - although it does include a lot of stuff that's more like 'extra features' than straight up 'fixes'.  But it does include everything I've changed in what I'm using in-game.. and all changes should be marked with 'MODIFY' or 'MODIFIED'.

 

 

Thanks. Grabbing, checking, and merging.

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