Jump to content

[LE] Is it possible to track if the player just used a specific soul gem?


JustChill

Recommended Posts

What I and anyone else would take personal is being called a jackass and continuous low key insults at every re-re-re-post.

I don't know if you asked Surfs, I don't know how Surfs got it. Who knows if Surfs had the right to give it to you. Clearly that is a raw

de-compiled script.

 

Are you suggesting that I posted a de-compiled script here? I would not use someone else's work without crediting them. The script I wrote for JustChill was written from scratch.

 

I hope you were talking about someone else. In that case I certainly agree doing that without crediting them and getting their permission is not acceptable.

Link to comment
Share on other sites

  • Replies 61
  • Created
  • Last Reply

Top Posters In This Topic

@SurfsideNaturals

I also agree with that. :happy:

 

Even though, I think that all scripts are similar at some point. We can surely write our own functions, but there are Papyrus functions hard-coded which simply can get used by all. With SKSE there are a few functions more too.

My initial "OnItemRemoved" script was a direct copy from the Wiki page with some additions. XD

But if you use some work arounds or get some solutions from another scripter, you should mention him / her.

 

To make it quick, here in the comments of this mod is a simple statement of what I think about credits at all:

https://steamcommunity.com/sharedfiles/filedetails/?id=1971792417

 

:smile:

 

 

Addition (02.02.2020):

 

Hey ReDragon2013,

I've compiled this one of yours now:

 

 

;Thanks to ReDragon2013 for this enhancement.
;+=Just Chill

Scriptname magicSoulTrapFXScript extends ActiveMagicEffect
{Scripted effect for the Soul Trap Visual FX}
; https://forums.nexusmods.com/index.php?/topic/8360833-is-it-possible-to-track-if-the-player-just-used-a-specific-soul-gem/

  GlobalVariable          PROPERTY SoulsCaught        auto
  _00E_SoulTrapController PROPERTY SoulTrapController auto    ; pointer to external script "_00E_SoulTrapController.pex"

  Message Property _00E_Failed      auto      ; _00E_FailedTrapping
  Message Property _00E_Success     auto      ; _00E_SuccessfulTrapping
  Message Property _00E_SoulPetty   auto
  Message Property _00E_SoulLesser  auto
  Message Property _00E_SoulCommon  auto
  Message Property _00E_SoulGreater auto
  Message Property _00E_SoulGrand   auto
  Message Property _00E_SoulHuman   auto

  Sound PROPERTY TrapSoundFX auto             ; played when we trap a soul, create a sound property we'll point to in the editor'

  ImageSpaceModifier PROPERTY TrapImod auto   ; IsMod applied when we trap a soul

  VisualEffect PROPERTY TargetVFX auto        ; {Visual Effect on Target aiming at Caster}
  VisualEffect PROPERTY CasterVFX auto        ; {Visual Effect on Caster aming at Target}

  EffectShader PROPERTY CasterFXS auto        ; {Effect Shader on Caster during Soul trap}
  EffectShader PROPERTY TargetFXS auto        ; {Effect Shader on Target during Soul trap}

  Bool PROPERTY bIsEnchantmentEffect auto     ; [Default=False]
    ; Set TRUE, if this soul trap is on a weapon enchantment or a spell that can do damage to deal with a fringe case

  Bool DeadAlready                            ; [Default=False]
  Bool victimIsNPC
  Int latch = 1

  Actor caster
  Actor victim

  int iSoulType
  int iSoulLevel

; -- EVENTs -- 2

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    victim = akTarget
    caster = akCaster

    myF_Init(akTarget)
    Countdown()
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
int i = 0
    WHILE (latch > i)
        Utility.Wait(0.1)
    ENDWHILE

    IF (victim) && (caster)
        myF_Finish()
    ENDIF
ENDEVENT


; -- FUNCTIONs -- 6

;--------------------------------
FUNCTION myF_Init(Actor akTarget)
;--------------------------------
    IF akTarget.HasKeyword( Game.GetForm(0x00013794) as Keyword )    ; [KYWD:00013794]  ActorTypeNPC
        victimIsNPC = TRUE
    ENDIF

    IF ( bIsEnchantmentEffect )
        ; do not pre-check for victims death
    ELSE
        DeadAlready = akTarget.IsDead()
    ENDIF
ENDFUNCTION


;-------------------
FUNCTION Countdown()
;-------------------
  latch -= 1
ENDFUNCTION


;-----------------------------------------
Bool FUNCTION myF_IsLevel(Int i, String s)
;-----------------------------------------
    RETURN (i < Game.GetGameSettingInt(s))
ENDFUNCTION


;------------------------------------
FUNCTION myF_CSG(SoulGem sg, Form fm)  ; exchange soulgems
;------------------------------------
    caster.RemoveItem(sg as Form, 1, TRUE)
    caster.AddItem(fm, 1, TRUE)
ENDFUNCTION


  GlobalVariable PROPERTY numSiraFillCounter auto        ; Have to be used a globalVar here !!!

;--------------------
FUNCTION myF_Finish()
;--------------------
 ; initiate lock to prevent multiple soul traps from processing at the same time

    WHILE (SoulTrapController) && !SoulTrapController.SecurePermission(caster)
        Utility.Wait(0.1)
    ENDWHILE

IF (deadAlready) || victim.IsDead() || (victim.GetActorValue("PerceptionCondition") == 0.0)
    IF ( SoulTrapController )
        SoulTrapController.ReleasePermission(caster)    ; release lock
    ENDIF
    RETURN    ; - STOP -
ENDIF
;=====================

    IF caster.GetItemCount(_00E_YerosCave_SiraSoulbender)
        IF (numSiraFillCounter.GetValue() >= 50.0)
            numSiraFillCounter.setValue(0)
            myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_WishWell_FrostcliffTavern_BrokenSoulgem)
        ENDIF
    ENDIF


    bool bOK    ; soulTrapped [default=False]


IF ( victimIsNPC )
    IF     (caster.GetItemCount(SoulGemBlack) > 0)
        bOK = TRUE
        myF_CSG(SoulGemBlack, SoulGemBlackFilled)

    ELSEIF (caster.GetItemCount(_00E_YerosCave_SiraSoulbender) > 0)
        bOK = TRUE
        myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_YerosCave_SiraSoulbender_FillGrand)
        numSiraFillCounter.Mod(1)                            ; increase globalVar threadsafe
    ENDIF

ELSE    ; victim is not a humanoid (remove Black Soul Gems from inventory before trap begins)

    int[] a = new Int[6]
        a[0] = caster.GetItemCount(SoulGemPetty)             ; numPetty
        a[1] = caster.GetItemCount(SoulGemLesser)            ; numLesser
        a[2] = caster.GetItemCount(SoulGemCommon)            ; numCommon
        a[3] = caster.GetItemCount(SoulGemGreater)           ; numGreater
        a[4] = caster.GetItemCount(SoulGemGrand)             ; numGrand
        a[5] = caster.GetItemCount(_00E_YerosCave_SiraSoulbender)

    iSoulType = 0                                        ; string soulType = "None"
    iSoulLevel = victim.GetLevel()                                ; targetLevel

    IF myF_IsLevel(iSoulLevel, "iLesserSoulActorLevel")
;--------------------
        iSoulType = 1        ; "petty"

        IF     (a[0] > 0)
            myF_CSG(SoulGemPetty, SoulGemPettyFilled)
            bOK = TRUE

         ELSEIF (a[1] > 0)
            myF_CSG(SoulGemLesser, _00E_SoulGemLesserFilledPetty)
            bOK = TRUE

        ELSEIF (a[2] > 0)
            myF_CSG(SoulGemCommon, _00E_SoulGemCommonFilledPetty)
            bOK = TRUE

        ELSEIF (a[3] > 0)
            myF_CSG(SoulGemGreater, _00E_SoulGemGreaterFilledPetty)
            bOK = TRUE

        ELSEIF (a[4] > 0)
            myF_CSG(SoulGemGrand, _00E_SoulGemGrandFilledPetty)
            bOK = TRUE

        ELSEIF (a[5] > 0)
            myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_YerosCave_SiraSoulbender_FillPetty)
            bOK = TRUE
            numSiraFillCounter.Mod(1)
        ENDIF

    ELSEIF myF_IsLevel(iSoulLevel, "iCommonSoulActorLevel")
;------------------------
        iSoulType = 2        ; "Lesser"

        IF     (a[1] > 0)
            myF_CSG(SoulGemLesser, SoulGemLesserFilled)
            bOK = TRUE
 
        ELSEIF (a[2] > 0)
            myF_CSG(SoulGemCommon, _00E_SoulGemCommonFilledLesser)
            bOK = TRUE

        ELSEIF (a[3] > 0)
            myF_CSG(SoulGemGreater, _00E_SoulGemGreaterFilledLesser)
            bOK = TRUE

        ELSEIF (a[4] > 0)
            myF_CSG(SoulGemGrand, _00E_SoulGemGrandFilledLesser)
            bOK = TRUE
 
        ELSEIF (a[5] > 0)
            myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_YerosCave_SiraSoulbender_FillLess)
            bOK = TRUE
            numSiraFillCounter.Mod(1)
        ENDIF

    ELSEIF myF_IsLevel(iSoulLevel, "iGreaterSoulActorLevel")
;------------------------
        iSoulType = 3        ; "Common"

        IF     (a[2] > 0)
            myF_CSG(SoulGemCommon, SoulGemCommonFilled)
            bOK = TRUE

        ELSEIF (a[3] > 0)
            myF_CSG(SoulGemGreater, _00E_SoulGemGreaterFilledCommon)
            bOK = TRUE

        ELSEIF (a[4] > 0)
            myF_CSG(SoulGemGrand, _00E_SoulGemGrandFilledCommon)
            bOK = TRUE

        ELSEIF (a[5] > 0)
            myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_YerosCave_SiraSoulbender_FillCom)
            bOK = TRUE
            numSiraFillCounter.Mod(1)
        ENDIF

    ELSEIF myF_IsLevel(iSoulLevel, "iGrandSoulActorLevel")
;------------------------
        iSoulType = 4        ; "Greater"

        IF     (a[3] > 0)
            myF_CSG(SoulGemGreater, SoulGemGreaterFilled)
            bOK = TRUE

        ELSEIF (a[4] > 0)
            myF_CSG(SoulGemGrand, _00E_SoulGemGrandFilledGreater)
            bOK = TRUE

        ELSEIF (a[5] > 0)
            myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_YerosCave_SiraSoulbender_FillGreat)
            bOK = TRUE
            numSiraFillCounter.Mod(1)
        ENDIF

    ELSE
;------------------------
        iSoulType = 5        ; "Grand"

        IF     (a[4] > 0)
            myF_CSG(SoulGemGrand, SoulGemGrandFilled)
            bOK = TRUE

        ELSEIF (a[5] > 0)
            myF_CSG(_00E_YerosCave_SiraSoulbender, _00E_YerosCave_SiraSoulbender_FillGrand)
            bOK = TRUE
            numSiraFillCounter.Mod(1)
        ENDIF
    ENDIF
ENDIF

        
; begin vanilla Soul Trap FX finale:

    IF ( bOK )
        victim.SetActorValue("PerceptionCondition", 0.0)
        PlayEffects(caster, victim)
        
        string s = " " + _00E_Success.GetName()            ; _00E_SuccessfulTrapping.GetName()     *** SKSE required ***

        IF     (iSoulType == 1)        ; "petty"
            Debug.Notification(_00E_SoulPetty.GetName()+s)
            SoulsCaught.Mod(1)

        ELSEIF (iSoulType == 2)        ; "lesser"
            Debug.Notification(_00E_SoulLesser.GetName()+s)
            SoulsCaught.Mod(1)

        ELSEIF (iSoulType == 3)        ; "common"
            Debug.Notification(_00E_SoulCommon.GetName()+s)
            SoulsCaught.Mod(1)

        ELSEIF (iSoulType == 4)        ; "greater"
            Debug.Notification(_00E_SoulGreater.GetName()+s)
            SoulsCaught.Mod(1)

        ELSEIF (iSoulType == 5)        ; "grand"
            Debug.Notification(_00E_SoulGrand.GetName()+s)
            SoulsCaught.Mod(1)
        ELSE
            _00E_SoulHuman.show()
        ENDIF

    ELSEIF ( victimIsNPC )
    
    ELSE
        _00E_Failed.show()
    ENDIF

;========================
; release lock
    IF ( SoulTrapController )
        SoulTrapController.ReleasePermission(caster)
    ENDIF
ENDFUNCTION


;---------------------------------------------------
FUNCTION PlayEffects(Actor akCaster, Actor akVictim)
;---------------------------------------------------
    TrapSoundFX.Play(akCaster)              ; Play TrapSoundFX sound from player
    TrapImod.Apply()                        ; Apply isMod at full strength

    TargetVFX.Play(akVictim, 4.7, akCaster) ; Play TargetVFX and aim them at the player
    CasterVFX.Play(akCaster, 5.9, akVictim)

    TargetFXS.Play(akVictim, 2)             ; Play effect shaders
    CasterFXS.Play(akCaster, 3)
ENDFUNCTION


SoulGem Property SoulGemBlack Auto
SoulGem Property SoulGemBlackFilled Auto


SoulGem Property SoulGemPetty Auto
SoulGem Property SoulGemPettyFilled Auto


SoulGem Property SoulGemLesser Auto
SoulGem Property SoulGemLesserFilled Auto
SoulGem Property _00E_SoulGemLesserFilledPetty Auto


SoulGem Property SoulGemCommon Auto
SoulGem Property SoulGemCommonFilled Auto
SoulGem Property _00E_SoulGemCommonFilledPetty Auto
SoulGem Property _00E_SoulGemCommonFilledLesser Auto


SoulGem Property SoulGemGreater Auto
SoulGem Property SoulGemGreaterFilled Auto
SoulGem Property _00E_SoulGemGreaterFilledPetty Auto
SoulGem Property _00E_SoulGemGreaterFilledLesser Auto
SoulGem Property _00E_SoulGemGreaterFilledCommon Auto


SoulGem Property SoulGemGrand Auto
SoulGem Property SoulGemGrandFilled Auto
SoulGem Property _00E_SoulGemGrandFilledPetty Auto
SoulGem Property _00E_SoulGemGrandFilledLesser Auto
SoulGem Property _00E_SoulGemGrandFilledCommon Auto
SoulGem Property _00E_SoulGemGrandFilledGreater Auto


SoulGem Property _00E_YerosCave_SiraSoulbender  Auto  
SoulGem Property _00E_YerosCave_SiraSoulbender_FillPetty  Auto  
SoulGem Property _00E_YerosCave_SiraSoulbender_FillLess  Auto
SoulGem Property _00E_YerosCave_SiraSoulbender_FillCom  Auto  
SoulGem Property _00E_YerosCave_SiraSoulbender_FillGreat  Auto  
SoulGem Property _00E_YerosCave_SiraSoulbender_FillGrand  Auto

MiscObject Property _00E_WishWell_FrostcliffTavern_BrokenSoulgem Auto

 

 

 

Unfortunately, when I cast the soul trap spell a second time onto a target, I receive a soul without even killing it.

 

Therefore I rather jump back to the original Enderal script which I initially posted, where this issue wasn't present.

 

Yet I will make a good use of your recommendations, thank you very much. :smile:

Link to comment
Share on other sites

 

Thanks again for all your help. :)

 

It works exactly as I hoped it would.

I either changed how soul gems get filled.

 

1 Grand soul can fill 5 petty soul gems.

1 Greater soul can fill 4 petty soul gems.

1 Common soul can fill 3 petty soul gems.

1 Lesser soul can fill 2 petty soul gems.

 

Which this logic, I simply made a loop for a more dynamical filling.

 

That new purple / magenta stripe effect that shoots into the air is the only downside of filling a big sould into a tiny soul gem.

Basically, you can now also get a filled petty soul gem, when you catch a grand soul. The only downside is that you will waste 4 petty soul gems that could have been filled either.

In such a case that effect that shoots these purple stripes into the air will be shown.

Mixing is either possible. If you have an empty common (3) and an empty lesser soul gem (+2) and you catch a grand soul, both of them will be filled (=5).

If you have 2 common soul gems in that case, you get one that is fully filled (3) and one that is filled with a lesser (+2) soul (=5)

 

 

I've had a watchful eye onto the Papyrus LOG, but I didn't got any warnings or errors, so I guess that's as good as it gets.

This is basically the script like it is used in Enderal, just with my additions.

The funny thing is, that they still use "TrapSoul" onto Black Soul gems, which still makes their filling to disappear. I've changed that to the AddItem function which is already used by the normal soul gems.

Yet I've included a function that gets called when a dynamic evaluation of removing and adding soul gems is necessary.

 

 

;Thanks to ReDragon2013 for good tips and enhancements.

;+= Just Chill



ScriptName magicSoulTrapFXScript extends ActiveMagicEffect

;=> The original script has to be overwritten as it already features an add- / removeItem function.

{Scripted effect for the Soul Trap Visual FX}



import debug



;======================================================================================;



;  PROPERTIES  /



;=============/



ImageSpaceModifier property TrapImod auto

{IsMod applied when we trap a soul}

sound property TrapSoundFX auto ; create a sound property we'll point to in the editor'

{Sound played when we trap a soul}

VisualEffect property TargetVFX auto

{Visual Effect on Target aiming at Caster}

VisualEffect property CasterVFX auto

{Visual Effect on Caster aming at Target}

EffectShader property CasterFXS auto

{Effect Shader on Caster during Soul trap}

EffectShader property TargetFXS auto

{Effect Shader on Target during Soul trap}

VisualEffect property WastedVFX auto

{Visual Effect on Target aiming up in the air}

VisualEffect property HeavenVFX auto

{Visual Effect on the air aming at Target}



bool property bIsEnchantmentEffect = false auto

{Set this to true if this soul trap is on a weapon enchantment or a spell that can do damage to deal with a fringe case}





;======================================================================================;



;  VARIABLES   /



;=============/



; objectreference playerref

bool DeadAlready = FALSE

bool bUseWait = True

bool soulWasted = false



;======================================================================================;



;  EVENTS      /



;=============/



;Declaring soul gem levels:



Event OnEffectStart(Actor akTarget, Actor akCaster)

    victim = akTarget

    caster = akCaster

    if(victim.HasKeyword(ActorTypeNPC))

        victimIsNPC = true

    endif

    if bIsEnchantmentEffect == False

        DeadAlready = Victim.IsDead()

    endif

    Countdown()

EndEvent



Event OnEffectFinish(Actor akTarget, Actor akCaster)

    Await()

    if victim

        ; initiate lock to prevent multiple soul traps from processing at the same time:

        if(SoulTrapController != None)

            while(!SoulTrapController.SecurePermission(caster))

                Utility.Wait(0.1)

            endWhile

        endif



        if(!deadAlready && victim.IsDead() && victim.GetActorValue("PerceptionCondition") != 0)

            bool soulTrapped = false

            String soulType = "None"



            ;if victim is not a humanoid, remove Black Soul Gems from inventory before trap begins:

            if(!victimIsNPC)

                ;numBlack = caster.GetItemCount(SoulGemBlack)

                ;caster.RemoveItem(SoulGemBlack, numBlack, true)

;=> I am not sure why the original script had to remove the black soul gems. I commented it out.

                numPetty = caster.GetItemCount(SoulGemPetty)

                numLesser = caster.GetItemCount(SoulGemLesser)

                numCommon = caster.GetItemCount(SoulGemCommon)

                numGreater = caster.GetItemCount(SoulGemGreater)

                numGrand = caster.GetItemCount(SoulGemGrand)



                int targetLevel = victim.GetLevel()



                if(targetLevel < Game.GetGameSettingInt("iLesserSoulActorLevel")) ;soul is petty

                    soulType="Petty"

                    if(numPetty > 0)

                        caster.RemoveItem(SoulGemPetty, 1, true)

                        caster.AddItem(SoulGemPettyFilled, 1, true)

                        soulTrapped = true

                    elseif (numLesser > 0)

                        caster.RemoveItem(SoulGemLesser, 1, true)

                        caster.AddItem(_00E_SoulGemLesserFilledPetty, 1, true)

                        soulTrapped = true

                    elseif(numCommon > 0)

                        caster.RemoveItem(SoulGemCommon, 1, true)

                        caster.AddItem(_00E_SoulGemCommonFilledPetty, 1, true)

                        soulTrapped = true

                    elseif(numGreater > 0)

                        caster.RemoveItem(SoulGemGreater, 1, true)

                        caster.AddItem(_00E_SoulGemGreaterFilledPetty, 1, true)

                        soulTrapped = true

                    elseif(numGrand > 0)

                        caster.RemoveItem(SoulGemGrand, 1, true)

                        caster.AddItem(_00E_SoulGemGrandFilledPetty, 1, true)

                        soulTrapped = true

                    elseif(caster.GetItemCount(_00E_YerosCave_SiraSoulbender))

                        caster.RemoveItem(_00E_YerosCave_SiraSoulbender, 1, true)

                        caster.AddItem(_00E_YerosCave_SiraSoulbender_FillPetty, 1, true)

                        soulTrapped = true

                        numSiraFillCounter.Mod(1)

                    endif



                elseif(targetLevel < Game.GetGameSettingInt("iCommonSoulActorLevel"));soul is lesser

                    soulType="Lesser"

                    if(numLesser > 0)

                        caster.RemoveItem(SoulGemLesser, 1, true)

                        caster.AddItem(SoulGemLesserFilled, 1, true)

                        soulTrapped = true

                    elseif(numPetty > 0)

                if numPetty >= 2

                                caster.RemoveItem(SoulGemPetty, 2, true)

                               caster.AddItem(SoulGemPettyFilled, 2, true)

                              soulTrapped = true

                else

                                caster.RemoveItem(SoulGemPetty, 1, true)

                               caster.AddItem(SoulGemPettyFilled, 1, true)

                              soulTrapped = true

                       soulWasted = true

                endif

                    elseif (numCommon > 0)

                        caster.RemoveItem(SoulGemCommon, 1, true)

                        caster.AddItem(_00E_SoulGemCommonFilledLesser, 1, true)

                        soulTrapped = true

                    elseif(numGreater > 0)

                        caster.RemoveItem(SoulGemGreater, 1, true)

                        caster.AddItem(_00E_SoulGemGreaterFilledLesser, 1, true)

                        soulTrapped = true

                    elseif(numGrand > 0)

                        caster.RemoveItem(SoulGemGrand, 1, true)

                        caster.AddItem(_00E_SoulGemGrandFilledLesser, 1, true)

                        soulTrapped = true

                    elseif(caster.GetItemCount(_00E_YerosCave_SiraSoulbender))

                        caster.RemoveItem(_00E_YerosCave_SiraSoulbender, 1, true)

                        caster.AddItem(_00E_YerosCave_SiraSoulbender_FillLess, 1, true)

                        soulTrapped = true

                        numSiraFillCounter.Mod(1)

                    endif



                elseif(targetLevel < Game.GetGameSettingInt("iGreaterSoulActorLevel")) ;soul is common

                    soulType="Common"

                    if(numCommon > 0)

                        caster.RemoveItem(SoulGemCommon, 1, true)

                        caster.AddItem(SoulGemCommonFilled, 1, true)

                        soulTrapped = true

            elseif (numPetty + numLesser) > 0

                soulTrapped = true

                DynamicGemFilling(3)

                    elseif(numGreater > 0)

                        caster.RemoveItem(SoulGemGreater, 1, true)

                        caster.AddItem(_00E_SoulGemGreaterFilledCommon, 1, true)

                        soulTrapped = true

                    elseif(numGrand > 0)

                        caster.RemoveItem(SoulGemGrand, 1, true)

                        caster.AddItem(_00E_SoulGemGrandFilledCommon, 1, true)

                        soulTrapped = true

                    elseif(caster.GetItemCount(_00E_YerosCave_SiraSoulbender))

                        caster.RemoveItem(_00E_YerosCave_SiraSoulbender, 1, true)

                        caster.AddItem(_00E_YerosCave_SiraSoulbender_FillCom, 1, true)

                        soulTrapped = true

                        numSiraFillCounter.Mod(1)

                    endif



                elseif(targetLevel < Game.GetGameSettingInt("iGrandSoulActorLevel")) ;soul is greater

                    soulType="Greater"

                    if(numGreater > 0)

                        caster.RemoveItem(SoulGemGreater, 1, true)

                        caster.AddItem(SoulGemGreaterFilled, 1, true)

                        soulTrapped = true

            elseif (numPetty + numLesser + numCommon) > 0

                soulTrapped = true

                DynamicGemFilling(4)

                    elseif(numGrand > 0)

                        caster.RemoveItem(SoulGemGrand, 1, true)

                        caster.AddItem(_00E_SoulGemGrandFilledGreater, 1, true)

                        soulTrapped = true

                    elseif(caster.GetItemCount(_00E_YerosCave_SiraSoulbender))

                        caster.RemoveItem(_00E_YerosCave_SiraSoulbender, 1, true)

                        caster.AddItem(_00E_YerosCave_SiraSoulbender_FillGreat, 1, true)

                        soulTrapped = true

                        numSiraFillCounter.Mod(1)

                    endif



                else

                    soulType="Grand"

                    if(numGrand > 0)

                        caster.RemoveItem(SoulGemGrand, 1, true)

                        caster.AddItem(SoulGemGrandFilled, 1, true)

                        soulTrapped = true

            elseif (numPetty + numLesser + numCommon + numGreater) > 0

                        soulTrapped = true

                DynamicGemFilling(5)

                    elseif(caster.GetItemCount(_00E_YerosCave_SiraSoulbender))

                        caster.RemoveItem(_00E_YerosCave_SiraSoulbender, 1, true)

                        caster.AddItem(_00E_YerosCave_SiraSoulbender_FillGrand, 1, true)

                        soulTrapped = true

                        numSiraFillCounter.Mod(1)

                    endif

                endif

            ; return Black Soul Gems:

            ;caster.AddItem(SoulGemBlack, numBlack, true)

            else

                numBlack = caster.GetItemCount(SoulGemBlack)

                if(numBlack > 0)

                    caster.RemoveItem(SoulGemBlack, 1, true)

                    caster.AddItem(SoulGemBlackFilled, 1, true)

                    soulTrapped = true

                elseif(caster.GetItemCount(_00E_YerosCave_SiraSoulbender))

                    caster.RemoveItem(_00E_YerosCave_SiraSoulbender, 1, true)

                    caster.AddItem(_00E_YerosCave_SiraSoulbender_FillGrand, 1, true)

                    soulTrapped = true

                    numSiraFillCounter.Mod(1)

                endif

            endif



            ; begin vanilla Soul Trap FX finale:

            if(soulTrapped == true)

                victim.SetActorValue("PerceptionCondition", 0)

                PlayEffects(caster, victim)

                if soulType=="Petty"

                    Debug.Notification(_00E_SoulPetty.GetName()+" "+_00E_SuccessfulTrapping.GetName())

                    SoulsCaught.Mod(1)

                elseif soulType=="Lesser"

                    Debug.Notification(_00E_SoulLesser.GetName()+" "+_00E_SuccessfulTrapping.GetName())

                    SoulsCaught.Mod(1)

                elseif soulType=="Common"

                    Debug.Notification(_00E_SoulCommon.GetName()+" "+_00E_SuccessfulTrapping.GetName())

                    SoulsCaught.Mod(1)

                elseif soulType =="Greater"

                    Debug.Notification(_00E_SoulGreater.GetName()+" "+_00E_SuccessfulTrapping.GetName())

                    SoulsCaught.Mod(1)

                elseif soulType =="Grand"

                    Debug.Notification(_00E_SoulGrand.GetName()+" "+_00E_SuccessfulTrapping.GetName())

                    SoulsCaught.Mod(1)

                else

                    _00E_SoulHuman.show()

                endif

            else

                _00E_FailedTrapping.Show()

            endif

        endif

        ; release lock

        SoulTrapController.ReleasePermission(caster)

    endif

endEvent





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Functions;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



Function DynamicGemFilling(int iSoulLevel)

    While iSoulLevel > 0

        if caster.GetItemCount(SoulGemPetty) > 0

                 caster.RemoveItem(SoulGemPetty, 1, true)

                 caster.AddItem(SoulGemPettyFilled, 1, true)

            iSoulLevel -= 1

        elseif caster.GetItemCount(SoulGemLesser) > 0

                     caster.RemoveItem(SoulGemLesser, 1, true)

            if (iSoulLevel - 2) >= 0

                        caster.AddItem(SoulGemLesserFilled, 1, true)

                   iSoulLevel -= 2

            else

                        caster.AddItem(_00E_SoulGemLesserFilledPetty, 1, true)

                   iSoulLevel -= 1                

            endif

        elseif caster.GetItemCount(SoulGemCommon) > 0

                     caster.RemoveItem(SoulGemCommon, 1, true)

            if (iSoulLevel - 3) >= 0

                         caster.AddItem(SoulGemCommonFilled, 1, true)

                    iSoulLevel -= 3

            elseif (iSoulLevel - 2) >= 0

                         caster.AddItem(_00E_SoulGemCommonFilledLesser, 1, true)

                    iSoulLevel -= 2

            else

                         caster.AddItem(_00E_SoulGemCommonFilledPetty, 1, true)

                    iSoulLevel -= 1

            endif

        elseif caster.GetItemCount(SoulGemGreater) > 0

                    caster.RemoveItem(SoulGemGreater, 1, true)

            if (iSoulLevel - 4) >= 0

                         caster.AddItem(SoulGemGreaterFilled, 1, true)

                    iSoulLevel -= 4

            elseif (iSoulLevel - 3) >= 0

                         caster.AddItem(_00E_SoulGemGreaterFilledCommon, 1, true)

                    iSoulLevel -= 3

            elseif (iSoulLevel - 2) >= 0

                         caster.AddItem(_00E_SoulGemGreaterFilledLesser, 1, true)

                    iSoulLevel -= 2

            else

                         caster.AddItem(_00E_SoulGemGreaterFilledPetty, 1, true)

                    iSoulLevel -= 1

            endif

        else

            iSoulLevel = -20    ;=> If we now have no soul gems left but still soul power, the soul was wasted.

        endif

    EndWhile

    if iSoulLevel == -20    ;=> Should be the only circumstance of a wasted soul here.

        soulWasted = true

    endif

EndFunction



Function PlayEffects(Actor akCaster, Actor akVictim)

  TrapSoundFX.Play(akCaster)              ; Play TrapSoundFX sound from player

  TrapImod.Apply()                        ; Apply isMod at full strength

  TargetVFX.Play(akVictim, 4.7, akCaster) ; Play TargetVFX and aim them at the player

  CasterVFX.Play(akCaster, 5.9, akVictim)

  TargetFXS.Play(akVictim, 2)             ; Play effect shaders

  CasterFXS.Play(akCaster, 3)

  if SoulWasted

    ObjectReference _00E_YC_SoulWastedMarker = akVictim.PlaceAtMe(XMarker, 1)

     _00E_YC_SoulWastedMarker.MoveTo(akVictim, 0.0, 0.0, 1000)

      WastedVFX.Play(akVictim, 4.7, _00E_YC_SoulWastedMarker) ; If a part of the soul wasn't captured it will flow right up into the air.

      HeavenVFX.Play(_00E_YC_SoulWastedMarker, 5.9, akVictim)

    soulWasted = false

    _00E_YC_SoulWastedMarker.Delete()

    _00E_YC_SoulWastedMarker = None

 endif

EndFunction



Function Countdown()

  latch -= 1

EndFunction



Function Await(int count = 0)

  while(latch > count)

    Utility.Wait(0.1)

  endwhile

EndFunction





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Properties + Variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



bool victimIsNPC



GlobalVariable Property SoulsCaught Auto

GlobalVariable Property numSiraFillCounter Auto



Actor caster

Actor victim



int latch = 1



int numPetty

int numLesser

int numCommon

int numGreater

int numGrand

int numBlack



_00E_SoulTrapController Property SoulTrapController Auto



Message Property _00E_FailedTrapping Auto

Message Property _00E_SuccessfulTrapping Auto

Message Property _00E_SoulPetty Auto

Message Property _00E_SoulLesser Auto

Message Property _00E_SoulCommon Auto

Message Property _00E_SoulGreater Auto

Message Property _00E_SoulGrand Auto

Message Property _00E_SoulHuman Auto



Actor Property PlayerREF Auto



Keyword Property ActorTypeNPC Auto



Static Property XMarker Auto



SoulGem Property SoulGemPetty Auto

SoulGem Property SoulGemPettyFilled Auto



SoulGem Property SoulGemLesser Auto

SoulGem Property SoulGemLesserFilled Auto

SoulGem Property _00E_SoulGemLesserFilledPetty Auto



SoulGem Property SoulGemCommon Auto

SoulGem Property SoulGemCommonFilled Auto

SoulGem Property _00E_SoulGemCommonFilledPetty Auto

SoulGem Property _00E_SoulGemCommonFilledLesser Auto



SoulGem Property SoulGemGreater Auto

SoulGem Property SoulGemGreaterFilled Auto

SoulGem Property _00E_SoulGemGreaterFilledPetty Auto

SoulGem Property _00E_SoulGemGreaterFilledLesser Auto

SoulGem Property _00E_SoulGemGreaterFilledCommon Auto



SoulGem Property SoulGemGrand Auto

SoulGem Property SoulGemGrandFilled Auto

SoulGem Property _00E_SoulGemGrandFilledPetty Auto

SoulGem Property _00E_SoulGemGrandFilledLesser Auto

SoulGem Property _00E_SoulGemGrandFilledCommon Auto

SoulGem Property _00E_SoulGemGrandFilledGreater Auto



SoulGem Property SoulGemBlack Auto

SoulGem Property SoulGemBlackFilled Auto



SoulGem Property _00E_YerosCave_SiraSoulbender  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillPetty  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillLess  Auto

SoulGem Property _00E_YerosCave_SiraSoulbender_FillCom  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillGreat  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillGrand  Auto

 

 

 

;Big thanks to  SurfsideNaturals for basically the whole script. ^^

;+=Just Chill



Scriptname _00E_YC_PlayerAlias_GemCheckSCR extends ReferenceAlias  



; EVENTS

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)



    If akDestContainer ; Gem was placed in container

        Return

    EndIf



    If akItemReference ; According to JustChill Gem was dropped. In some circumstances this could still fill if the gem was removed by the game. Sould be fully tested.

        Return

    EndIf



    If CheckGems(akBaseItem)

        if numSiraFillCounter.GetValue() >= 50

            numSiraFillCounter.setValue(0)

            P.AddItem(_00E_WishWell_FrostcliffTavern_BrokenSoulgem, 1)

        else

            P.AddItem(_00E_YerosCave_SiraSoulbender, 1, True) ; P will be replaced with GetReference() when script is added to the Quest Alias.

        endif

    EndIf



; You could run a function here to make sure there is only 1 gem in the players inventory and remove any extra as a safety precaution.

    RemoveGemOverkill()

endEvent



Event OnInit() ; Fill Properties, Set up Array and Event Filter

    SoulGems = new Form[5]

    SoulGems[0] = _00E_YerosCave_SiraSoulbender_FillPetty As Form

    SoulGems[1] = _00E_YerosCave_SiraSoulbender_FillLess As Form

    SoulGems[2] = _00E_YerosCave_SiraSoulbender_FillCom As Form

    SoulGems[3] = _00E_YerosCave_SiraSoulbender_FillGreat As Form

    SoulGems[4] = _00E_YerosCave_SiraSoulbender_FillGrand As Form



    P = GetReference() As ObjectReference ; Once this is on the Player Ref Alias you will use a differnt function.

;=> Hm... I tried. :( That Property is bound ot the very exact Alias Entry in the quest.

;===> In addition: Thanks for the update, SurfsideNaturals. This works now very well. :D

    SetFilter()



    GoToState("Set") ; Make sure this event only runs once.



endEvent



; EVENTS END



; FUNCTIONS

Function SetFilter() ; Add SoulGem Forms to the Filter so only these Forms will Trigget this Event.

    Int i

    While i < 5

        AddInventoryEventFilter(SoulGems[i])

        i += 1

    EndWhile

EndFunction   



Function RemoveGemOverkill()

    int GemCount = P.GetItemCount(_00E_YerosCave_SiraSoulbender)

    If GemCount > 1

        P.RemoveItem(_00E_YerosCave_SiraSoulbender, (GemCount - 1), true)

    endif

EndFunction



Bool Function CheckGems(Form G) ; Make sure the item removed is one of the Gems.

    Int i

    While i < 5

        If G == SoulGems[i]

        Return True

        EndIf

        i += 1  

    EndWhile

EndFunction   



; FUNCTIONS END



; STATES  

State Set  ; the need for this can be removed when testing is done and the script is moved to the Quest Alias.

    Event OnInit()

    endEvent

    Function SetFilter()

    EndFunction   

EndState



; STATES END



; PROPERTIES



SoulGem Property _00E_YerosCave_SiraSoulbender  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillPetty  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillLess  Auto

SoulGem Property _00E_YerosCave_SiraSoulbender_FillCom  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillGreat  Auto  

SoulGem Property _00E_YerosCave_SiraSoulbender_FillGrand  Auto



GlobalVariable Property numSiraFillCounter Auto



MiscObject Property _00E_WishWell_FrostcliffTavern_BrokenSoulgem Auto



Form[] SoulGems

ObjectReference P



; PROPERTIES END

 

I basically let this one like it is. XD

Still don't really get why this works as it does. Never seen anything familiar like that in Gamebryo. :(

Quest Aliases with script. Stone the crows!

 

Special thanks to you again SurfesideNaturals for your perfect example.

Such alias scripts could get handy. ;)

 

Yet I´am now into the more awful bit.

Nav Mesh placement 'n stuff... -.-

 

Cheers

Link to comment
Share on other sites

your code

    P = GetReference() As ObjectReference ; Once this is on the Player Ref Alias you will use a differnt function.

a bit smaller

    P = self.GetReference()   ; Once this is on the PlayerRef Alias you will use a different function.

a bit more optimization

 

EVENT OnInit()
    gotoState("Set") ; Make sure this event only runs once.
    RegisterForSingleUpdateGameTime(0.0)
ENDEVENT


; STATES  
;=======================
State Set
;======
    EVENT OnInit()
    ENDEVENT

    EVENT OnUpdateGameTime()  ; Set up Array and Event Filter
        SoulGems = new Form[5]
        SoulGems[0] = _00E_YerosCave_SiraSoulbender_FillPetty As Form
        SoulGems[1] = _00E_YerosCave_SiraSoulbender_FillLess As Form
        SoulGems[2] = _00E_YerosCave_SiraSoulbender_FillCom As Form
        SoulGems[3] = _00E_YerosCave_SiraSoulbender_FillGreat As Form
        SoulGems[4] = _00E_YerosCave_SiraSoulbender_FillGrand As Form

        P = self.GetReference()     ; if runs on PlayerAlias script (Game.GetPlayer() == self.GetReference() as Actor)

;=> Hm... I tried. :( That Property is bound ot the very exact Alias Entry in the quest.
;===> In addition: Thanks for the update, SurfsideNaturals. This works now very well. :D

 ;;;       SetFilter()
        int i = 0
        WHILE (i < 5)
            self.AddInventoryEventFilter(SoulGems[i])
            i = i + 1
       ENDWHILE
    ENDEVENT
;======
endState

Edited by ReDragon2013
Link to comment
Share on other sites

Thank you, I've added and tested your enhancements.

Everything works the same, and no Papyrus log entries about any issues so I guess it's as good as before just better. :D

 

This seems to be a similar case like in New Vegas with "clean" modding. ^^

 

That's also a reason why I used this:

  if SoulWasted
    ObjectReference _00E_YC_SoulWastedMarker = akVictim.PlaceAtMe(XMarker, 1)
     _00E_YC_SoulWastedMarker.MoveTo(akVictim, 0.0, 0.0, 1000)
      WastedVFX.Play(akVictim, 4.7, _00E_YC_SoulWastedMarker) ; If a part of the soul wasn't captured it will flow right up into the air.'
      HeavenVFX.Play(_00E_YC_SoulWastedMarker, 5.9, akVictim)
    soulWasted = false
    _00E_YC_SoulWastedMarker.Delete()  ;=> I hope this works similar as "MarkForDelete" from New Vegas.
    _00E_YC_SoulWastedMarker = None
 endif

I am not sure how clean "PlaceAtMe" in Skyirm works, but from Oblivion to New Vegas, this was a function that had to be taken care of as it bloats your savegame.

Creating a reference variable on the PlaceAtMe-object was always a good idea as of connecting it with a Delete-function, which will remove it from the savegame.

Even though "MarkForDelete" in New Vegas worked only on disabled references. Seems the Delete()-function here doesn't bother about that.

XMarker

Is actually the wrong name, as the property is in fact connected with the XMarkerHeading. XMarker has no 3D Data and therefore produced errors in the Papyrus LOG (even though it still worked ingame XD), so I switched it to the Headng.

This basically ensures that the new magenta soul stripe effect shoots up into the air, when a soul is wasted.

 

I am not sure if

_00E_YC_SoulWastedMarker = None

is necessary.

 

 

Remember that Delete() only flags an object for deletion; the actual deletion takes place later. Per this USKP discussion, if a variable still points to the object, the object will remain temporarily persistent; the deletion won't occur until that variable is cleared (i.e. by setting it to None).

An object reference variable should also fall under that case.

 

In addition

 


Flags this object reference as wanting to be deleted. A reference that is flagged for delete will be deleted as soon as:

  • It is no longer in a script property

Ah, well even though it's an object reference variable that's still good to know. :smile:

Link to comment
Share on other sites

I am glad to see your mod going so well. :dance: It seems you are starting to catch on to Papyrus. :wub:

 

Here is an optimized version of your script. I see you are using a GlobalVariable. That will work just fine, but I prefer using VM quest variables. You do have a quest here and can look into that if you are interested.

 

You were also adding the broken gem to the player with the message showing. Remember the player is not supposed to know the gem is being added and removed.

 

If you are using Oninit() and are running large functions, then you should use OnUpdate or OnUpdateGameTime(). In this case you are only setting the filters.

 

As you can see the Soul Gem Array has been changed. This involves you filling the array in properties. Do you see the little Array check box?? You can delete your filled soulgem properties and add them to the Array in "Properties"

 

I also updated your functions for adding the gem and checking the gems because you updated the script.

 

getreference() returns and object reference so you do not need to cast it as an object reference.

;Big thanks to SurfsideNaturals for helping me. ^^

;+=Just Chill 


Scriptname _00E_YC_PlayerAlias_GemCheckSCR extends ReferenceAlias 

; EVENTS
Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
    
    If akDestContainer ; Gem was placed in container
        Return
    EndIf

    If akItemReference ; According to JustChill Gem was dropped. In some circumstances this could still fill if the gem was removed by the game. Sould be fully tested.
        Return
    EndIf

    If CheckGems(akBaseItem)
        AddGem(GetReference())
    EndIf

endEvent

Event OnInit() ; In some cases OnInit() will fire more than once and it can make a mess with some scripts. I do not think it will fire here twice on a start game enabled quest. Even if it dose it will have no negative impact on the script. No need for a state.
    Int i
    While i < 5
        AddInventoryEventFilter(SoulGemArray[i] As Form)
        i += 1
    EndWhile
endEvent

; EVENTS END

; FUNCTIONS START

Function AddGem(ObjectReference P)

    Form G = FindGem()

        int GC = P.GetItemCount(G)
        If GC
            If GC > 1
                P.RemoveItem(G, GC - 1, true)
            EndIf
        Else 
            P.AddItem(G, 1, True)
        EndIf    

EndFunction

Form Function FindGem()

    If numSiraFillCounter.GetValue() > 49
        numSiraFillCounter.setValue(0) 
        Return _00E_WishWell_FrostcliffTavern_BrokenSoulgem As Form
    Else
        Return _00E_YerosCave_SiraSoulbender As Form
    EndIf

EndFunction    

Bool Function CheckGems(Form G) ; Make sure the item removed is one of the Gems.
    Int i
    While i < 5
        If G == SoulGemArray[i] As Form
        Return True
        EndIf
        i += 1  
    EndWhile
EndFunction   

; PROPERTIES START

SoulGem Property _00E_YerosCave_SiraSoulbender  Auto  
SoulGem[] Property SoulGemArray  Auto  
GlobalVariable Property numSiraFillCounter Auto
MiscObject Property _00E_WishWell_FrostcliffTavern_BrokenSoulgem Auto

; PROPERTIES END

Great Job!! :thumbsup:

Link to comment
Share on other sites

XD

I like how you changed my initial

"Big thanks to SurfsideNaturals for basically the whole script"

to

"Big thanks to SurfsideNaturals for helping me"

^^

 

 

Thanks for pointing out that you either can set arrays in properties. This seems to be pretty convenient. :smile:

 

 

I am either interested in Quest Variables but had no idea how I can set them up for the CK.

 

In New Vegas it simply worked like that:

if (Questname).(Variable name) == Whatever

I might set up a quest property here and simply try it out like above but just by using the quest property then.

Hopefully that will work.

 

 

Thank you for your continuous support. :)

Link to comment
Share on other sites

  • 2 weeks later...

Hey thanks again for your enhancements.

 

I had some different tasks on this weekend, but finally got my hands in this one again.

 

And as of altering the way catching souls work, it of course did cause issues with re-adding the empty Soulbender into the inventory.

Yet as of current tests it seems I covered these issues. :D

 

 

 

;Big thanks to SurfsideNaturals for helping me. ^^

;+=Just Chill


Scriptname _00E_YC_PlayerAlias_GemCheckSCR extends ReferenceAlias

; EVENTS

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

    If akDestContainer ; Gem was placed in container
        Return
    EndIf

    If akItemReference ; According to JustChill Gem was dropped. In some circumstances this could still fill if the gem was removed by the game. Sould be fully tested.
        Return
    EndIf

    If CheckGems(akBaseItem)
        AddGem(GetReference())
    EndIf

endEvent


Event OnInit() ; In some cases OnInit() will fire more than once and it can make a mess with some scripts. I do not think it will fire here twice on a start game enabled quest. Even if it dose it will have no negative impact on the script. No need for a state.

    Int i
    While i < 5
        AddInventoryEventFilter(SoulGemArray[i] As Form)
        i += 1
    EndWhile

endEvent

; EVENTS END

; FUNCTIONS START

Function AddGem(ObjectReference P)    ;=> I somewhat liked to do all stuff here as of having it easier to track and fix issues.
                                    ;=> So I got rid of the FindGem() function.
        if SiraSoulGemFunctions.ycInt_SiraSoulCounter > 49    ;=> Quest Script Variable :)
            P.Additem(_00E_WishWell_FrostcliffTavern_BrokenSoulgem, 1, True)
            SiraSoulGemFunctions.ycInt_SiraSoulCounter = -1
        elseif SiraSoulGemFunctions.ycInt_SiraSoulCounter > -1
            if UI.IsMenuOpen("InventoryMenu")        ;=> A Soul Gem can only be used in inventory menu
                int[] SoulGemC = new int[6]            ;=> Used to take care of eventualities.
                SoulGemC[0] = P.GetItemCount(_00E_YerosCave_SiraSoulbender)    ;=> Like being in a filling process and
                SoulGemC[1] = P.GetItemCount(SoulGemArray[0])                ;=> quickly opening the menu.
                SoulGemC[2] = P.GetItemCount(SoulGemArray[1])    ;=> That would have resulted in multiple gems being
                SoulGemC[3] = P.GetItemCount(SoulGemArray[2])    ;=> added. Now we only have one.
                SoulGemC[4] = P.GetItemCount(SoulGemArray[3])
                SoulGemC[5] = P.GetItemCount(SoulGemArray[4])
                if (SoulGemC[0] + SoulGemC[1] + SoulGemC[2] + SoulGemC[3] + SoulGemC[4] + SoulGemC[5]) == 0
                        P.AddItem(_00E_YerosCave_SiraSoulbender, 1, True)
                endif
            endif
        endif                    
        int GC = P.GetItemCount(_00E_YerosCave_SiraSoulbender)
        If GC > 1        ;=> Just to be sure we only have one empty gem in inventory. ^^
            P.RemoveItem(_00E_YerosCave_SiraSoulbender, GC - (GC - 1), true)
        EndIf   ;=> Thanks for making me aware that Papyrus likes firing on weird eventualities. XD

EndFunction    

Bool Function CheckGems(Form G) ; Make sure the item removed is one of the Gems.

    Int i
    While i < 5
        If G == SoulGemArray[i] As Form
        Return True
        EndIf
        i += 1  
    EndWhile

EndFunction   

; PROPERTIES START

SoulGem Property _00E_YerosCave_SiraSoulbender  Auto  
SoulGem[] Property SoulGemArray  Auto

MiscObject Property _00E_WishWell_FrostcliffTavern_BrokenSoulgem Auto

_00E_YerosCave_SiraVariableSCR Property SiraSoulGemFunctions hidden
    _00E_YerosCave_SiraVariableSCR function get()
        return Quest.GetQuest("_00E_YerosCave_SiraGemCheckQST") as _00E_YerosCave_SiraVariableSCR
    endFunction
endProperty

; PROPERTIES END

 

 

 

 

But after all, without your help SurfsideNaturals I wouldn't have got that far. :smile:

Link to comment
Share on other sites

Nothing, the script is fine. ^^

But I may explain the issues I had to overcome:

 

The gems are dropped and placed in containers when in menu also.

 

Yes, but we catched that already by having a target container reference.

And we catched removing the gem not into world space by having an item reference.

 

 

The problem is that you can also fill the Soulbender til it is fully filled, as of my recent changes to how catching souls work.

So when you just have a Bender filled with a petty soul in your inventory, you can catch a greater soul with it and you will have a bender filled with a grand soul.

As in that case the one with the petty soul is removed and of course the re-adding fires too.

 

But I catched that already by the queries I added.

 

 

First of all, I tried it with multiple enemies at once.

So I had 3 birds that give a petty soul. Got them all with a Soultrap effect and then killed them one by another in console window.

Which means when I left the console window, I had 3 corpses and all of them were able to fill the bender.

Luckily the magic script has a controlling process so you cannot catch multiple souls in the very exact same second, but one after another (with a wait time of around half a second).

 

Initially I got multiple Soulbenders into the inventory as of these changes. But these got catched by quering for UI.IsMenuOpen("InventoryMenu"). This solved the issue.

 

Then, I made another test.

I again, catched the souls of the 3 birds, but after leaving the console, I immediately opened the inventory menu while the soul catching was still in process.

And I got another spam of Soulbenders. XD

So I added the harsh query about having literally NO soul bender in the inventory, which is the only case you can get an empty one.

Now when I tested it the same way, I was able to see how the bender got filled with the 3 souls, but without getting any additional bender into the menu. :D

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...