Jump to content
ℹ️ Intermittent Download History issues ×

ReDragon2013

Members
  • Posts

    640
  • Joined

  • Last visited

Posts posted by ReDragon2013

  1. I have rewritten the script "xMATHICombatLogic.psc". If you like notify the mod author of perma.

    Maybe he likes to make a hotfix for that specific script.

     

    Mod: "T3nd0's Perkus Maximus" by T3nd0
    http://www.nexusmods.com/skyrim/mods/59849/?

     

     

     

    Scriptname xMATHICombatLogic extends ActiveMagicEffect  
    {rewritten by ReDragon 2016}    ; this script needs SKSE during gameplay and compiling !!!
    
      Perk PROPERTY xmaDexRemovingTheScaffold auto
      Perk PROPERTY xmaDexMonkeyGrip auto
      Perk PROPERTY xmaLIAEndeavor0  auto
      Perk PROPERTY xmaLIAEndeavor1  auto
    
      Spell PROPERTY xMALIAEndeavor0Spell auto
      Spell PROPERTY xMALIAEndeavor1Spell auto
    
      Keyword  PROPERTY xmaweaptypefist         auto
      FormList PROPERTY xMADEXDontStealFormList auto        ; new entry made by mod author
    
      Actor target = none
    
    
    ; -- EVENTs --
    
    EVENT OnEffectStart(Actor akTarget, Actor akCaster)
        target = akTarget                                    ; make target persistent for a while
    ENDEVENT
    
    EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
        target = None                                        ; IF magic effect has been finished target becomes <None>
    ENDEVENT
    
    
    ;======================================
    State busy
    ;=========
    EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
    ENDEVENT
    ;=======
    endState
    
    
    EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
        gotoState("busy")                ; ### STATE ###
    
        IF (akSource as Weapon) && (akSource as Weapon).HasKeyword(xmaweaptypefist)
            myF_Action(akAggressor, abHitBlocked)
        ENDIF
    
        IF ( abHitBlocked )
        ELSE
            myF_Cast()
        ENDIF
    
    IF ( target )
        gotoState("")                    ; ### STATE ### back to empty state, if target is still valid
    ENDIF
    ENDEVENT
    
    
    ; -- FUNCTIONs -- 2
    
    ;------------------
    FUNCTION myF_Cast()        ; abHitBlocked is False
    ;------------------
        objectReference oRef = target as ObjectReference
    
    IF ( oRef )
        ; keep target alive within this function
    ELSE
        RETURN    ; - STOP -    target is <None>
    ENDIF
    ;---------------------
    IF (oRef as Actor).HasPerk(xMAliaEndeavor1)        ; former error line (79)
        xMAliaEndeavor1Spell.Cast(oRef, oRef)
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
    IF (oRef as Actor).HasPerk(xMAliaEndeavor0)        ; former error line (81)
        xMAliaEndeavor0Spell.Cast(oRef, oRef)
    ENDIF
    ENDFUNCTION
    
    
    ;----------------------------------------------------
    FUNCTION myF_Action(ObjectReference agR, Bool bBlock)
    ;----------------------------------------------------
    ; agR    = akAggressor
    ; bBlock = abHitBlocked
    
    IF (agR as Actor)
    ELSE
        RETURN    ; - STOP -    aggressor is not valid
    ENDIF
    ;---------------------
        actor aRef = target
        armor AR                    ; use this as placeholder for all armor types
    
    IF ( aRef )
        ; keep target alive within this function
    ELSE
        RETURN    ; - STOP -    target is <None>
    ENDIF
    ;---------------------
    ;; monkey grip
    
    IF (bBlock) && (agR as Actor).HasPerk(xmadexmonkeygrip)
        AR = aRef.GetEquippedShield()                    ; Shield
        IF (AR) && !(xMADEXDontStealFormList.HasForm(AR as Form))
            aRef.UnequipItem(AR, False)
            aRef.RemoveItem(AR, 1)
            agR.AddItem(AR, 1)
        ENDIF
        RETURN    ; - STOP -    abHitBlocked is TRUE, short circuit
    ENDIF
    ;---------------------
    ;; removing the scaffold
    
    IF (!bBlock) && (agR as Actor).HasPerk(xmadexremovingthescaffold)
    ELSE
        RETURN    ; - STOP -    no perk for scaffold action
    ENDIF
    ;---------------------
    ; It looks like Helmet and Gantlets are not in correct slots.
    ; Its better to add these lines of code instead of replacing the old ones.
    ; This way we are sure this will always work,
    
    ; ------------------------------------------------------
    ;  --- YOU have to use SKSE extender for compiling! ---
    ; ------------------------------------------------------
    ;**
        AR = aRef.GetWornForm(0x00000010) as Armor        ; Forearms    *SKSE* needed!
        IF ( AR )
        ELSE
    ;**
            AR = aRef.GetWornForm(0x00000008) as Armor    ; Hands        *SKSE*
        ENDIF
    
    IF (AR) && !(xMADEXDontStealFormList.HasForm(AR))
        aRef.UnequipItem(AR, False)
        aRef.RemoveItem(AR, 1)
        agR.AddItem(AR, 1)
        RETURN    ; - STOP -    armor found / 1
    ENDIF
    ;---------------------
    ;**
        AR = aRef.GetWornForm(0x00000001) as Armor        ; Head        *SKSE*
        IF ( AR )
        ELSE
    ;**
            AR = aRef.GetWornForm(0x00000002) as Armor    ; Hair        *SKSE*
        ENDIF
    
    IF (AR) && !(xMADEXDontStealFormList.HasForm(AR))
        aRef.UnequipItem(AR, False)
        aRef.RemoveItem(AR, 1)
        agR.AddItem(AR, 1)
        RETURN    ; - STOP -    armor found / 2
    ENDIF
    ;---------------------
    ;**
        AR = aRef.GetWornForm(0x00000080) as Armor        ; Leg        *SKSE*
    
    IF (AR) && !(xMADEXDontStealFormList.HasForm(AR))
        aRef.UnequipItem(AR, False)
        aRef.RemoveItem(AR, 1)
        agR.AddItem(AR, 1)
        RETURN    ; - STOP -    armor found / 3
    ENDIF
    ;---------------------
    ;**
        AR = aRef.GetWornForm(0x00000004) as Armor        ; Body        *SKSE*
    
    IF (AR) && !(xMADEXDontStealFormList.HasForm(AR))
        aRef.UnequipItem(AR, False)
        aRef.RemoveItem(AR, 1)
        agR.AddItem(AR, 1)
    ENDIF
    ENDFUNCTION

     

     

  2. I see YOU FOUND the mistake, well done! Do not forget Skyrim is multithreading.

    First of all you should have more respect if somebody answers to your posting. Each nexus user spends time (spare time) to give you depends on his knowledge a best as possible answer/solution.

    Your papyrus coding style is horrible. The script (and archive) you provided here is far away to be easy to understand. I tried my best to make it readable.
    Your archive is missing of "stringUtil.psc" and "miscUtil.psc". The first script I found in SKSE script extender package. About the second I have no idea.

    Here is the result of my scripting re-work. Read my intern comments carefully!

     

     

    Scriptname SVE_ParserEngine extends Quest
    {rewritten by ReDragon 2016}
    
     ;Import StringUtil                        ; a bad idea to do that, only for scripting experts useful (ReDragon)
    
      FormList PROPERTY fml_Shout   auto    ; ShoutFormList
      FormList PROPERTY fml_Spell   auto    ; SpellFormList
      FormList PROPERTY fml_Command auto    ; CommandFormList
      FormList PROPERTY fml_Armor   auto    ; ArmorFormList
      FormList PROPERTY fml_Arrow   auto    ; ArrowFormList
      FormList PROPERTY fml_Weapon  auto    ; WeaponFormList
      FormList PROPERTY fml_Summon  auto    ; SummonFormList
    
     ;Actor PROPERTY PlayerRef auto            ; UnUSED by now
      Actor PROPERTY TargetRef auto            ; UnUSED !?
    
     ;Int[] fCommandList                    ; UnUSED // keeps track of the frequencies of usage
     ;String[] EquipSlots                     ; UnUSED // list of places armor can be equipped
    
    ; array string lists
      String[] s_DA                            ; SVE_DumpArray
      String[] s_CMD                        ; CommandList
      string[] s_Material                    ; MaterialList
      string[] s_Weapon                        ; WeaponTypes
      string[] s_Armor                        ; ArmorTypes
    
      string[] sn_Armor                        ; ArmorNames // list of unique phrases associated with specific armors
      string[] sn_Weapon                    ; WeaponNames // list of unique phrases associated with specific weapons
    
      string CurrentDump                    ; text data string holder
      Int    DumpLineCount                    ; max. text lines of data string
    
    ; Debugging only, should be removed on mod release
      Float StartTime
    
    
    ; -- EVENTs -- 2
    
    EVENT OnInit()
        RegisterForSingleUpdateGameTime(0.0)        ; use only fast code here, otherwise run it asynchronously
    ENDEVENT
    
    EVENT OnUpdateGameTime()    ; this is SKYRIM event, FallOut 4 has other event for that
        myF_Init_Arrays()
        Main()
        myF_CleanUp_Arrays()
    
        CurrentDump = ""
        DumpLineCount = 0
    ENDEVENT
    
    
    ; -- FUNCTIONs -- 9
    
    ;----------------------------
    FUNCTION myF_CleanUp_Arrays()
    ;----------------------------
        string[] b            ; empty array to make arrays on top <None>
    
        s_DA = b            ; SVE_DumpArray
        s_CMD = b            ; CommandList
    
        s_Material = b        ; MaterialList
    
        s_Weapon = b        ; WeaponTypes
        s_Armor    = b            ; ArmorTypes
    
        sn_Armor  = b        ; ArmorNames
        sn_Weapon = b        ; WeaponNames
    ENDFUNCTION
    
    
    ;-------------------------
    FUNCTION myF_Init_Arrays()
    ;-------------------------
    ; #######
        Debug.Trace("SVE_TEST: Initializing SVE_Arrays")
    ; #######
        s_DA = new String[100]                ; space for dump data
    
    ; // commands //
    ;;;    fCommandList = new Int[10]          ;
        s_CMD = new String[10]                 ; list of commands
    
        s_CMD[0] = "Thuum"
        s_CMD[1] = "Equip"
        s_CMD[2] = "Unequip"
        s_CMD[3] = "Use"
        s_CMD[4] = "Cast"
        s_CMD[5] = "Map"
        s_CMD[6] = "Save"
        s_CMD[7] = "Exit"
    
    ; // materials //
        s_Material = new String[20]         ; list of predefined materials [10]
    
        s_Material[0] = "Iron"                  ; Eisen
        s_Material[1] = "Steel"                 ; Stahl
        s_Material[2] = "Dwarven"        
        s_Material[3] = "Dragonbone"            ; Drachenknochen
        s_Material[4] = "Ebony"            
        s_Material[5] = "Chitin"
        s_Material[6] = "Glass"                 ; Vulkanglas
        s_Material[7] = "Gold"
        s_Material[8] = "Silver"                ; Silber
        s_Material[9] = "Dwemer"
    
    ; // weapons //
        s_Weapon = new String[20]            ; list of predefined weapon types [10]
    
        s_Weapon[0] = "Sword"                    ; Schwert
        s_Weapon[1] = "Dagger"                   ; Dolch
        s_Weapon[2] = "Bow"                      ; Bogen
        s_Weapon[3] = "Staff"                    ; Zauberstab
        s_Weapon[4] = "Greatsword"               ; Langschwert
        s_Weapon[5] = "Crossbow"                 ; Armbrust
        s_Weapon[6] = "Blade"                    ;
        s_Weapon[7] = "Mace"                     ; Streitkolben
        s_Weapon[8] = "Warhammer"                ; Kriegshammer
        s_Weapon[9] = "Battleaxe"                ; Großaxt
    ;;; s_Weapon[10]= "Katana"
    
    ; // armors //
    ;;;    EquipSlots = new string[20]         ;
        s_Armor = new string[10]             ; list of predefined armor types that can be equipped [6]
    
        s_Armor[0] = "Helmet"                    ; Helm
        s_Armor[1] = "Breastplate"               ; Brustpanzer
        s_Armor[2] = "Boots"                     ; Schuhe
        s_Armor[3] = "Gauntlets"                 ; Handschuhe
        s_Armor[4] = "Shield"                    ; Schild
        s_Armor[5] = "Armor"                     ; Rüstung
    
    ; // unique phrases //
    
        sn_Armor  = new String[100]            ; list of unique phrases associated with specific armors
        sn_Weapon = new String[100]            ; list of unique phrases associated with specific weapons
    
        sn_Armor[0]  = "Hardening"
    
        sn_Weapon[0] = "Woe"
        sn_Weapon[1] = "Nightingale"
        sn_Weapon[2] = "Miraak"
        sn_Weapon[3] = "Magus"
    ENDFUNCTION
    
    
    ;------------------------------
    Int FUNCTION myF_GetDumpLines()
    ;------------------------------
    ;Find out how many distinct lines are in the string
    ; *******************************************************************************
    ; *** I assume string "CurrentDump" has been declared on top as heap variable ***
    ; *******************************************************************************
    
        int LineCountStartIndex = 0
        int LineCount = 0
    
    ; the next loop is a bit strange because of twice Find(), should be carefully optimized (ReDragon 2016)
    
    int i = 0                                                            ; i = NullCharIndex
        WHILE (i != -1)
            i = StringUtil.Find(CurrentDump, "/n", LineCountStartIndex)    ; "/n" is EOLN which means end of line
            LineCount += 1
            LineCountStartIndex = i + 2
            i = StringUtil.Find(CurrentDump, "/n", LineCountStartIndex)    ; to prevent an extra line being added
        ENDWHILE
    
        RETURN LineCount
    ENDFUNCTION
    
    
    ;-----------------------------
    FUNCTION myF_GetDump(String s)    ; "s" means stringFileName
    ;-----------------------------
    ; shout out to MinionMaster for helping me understand the syntax and
    ; Find the right functions in "MiscUtil.psc" this function is his work
    ; *******************************************************************************
    ; *** I assume string "CurrentDump" has been declared on top as heap variable ***
    ; *** I assume int "DumpLineCount" has been declared on top as heap variable  ***
    ; *******************************************************************************
    
    ; #######
        Debug.Trace("SVE_TEST: dumping in progress for " +s)
    ; #######
    
    IF MiscUtil.FileExists(s)                                        ; *** script MiscUtil.psc is unknown ***
    ELSE
        Debug.Trace("SVE_TEST -- Error 01 -- file not found!")
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
        CurrentDump   = MiscUtil.ReadFromFile(s)                    ; READ DUMP
        DumpLineCount = myF_GetDumpLines()                            ; GET max lines for current dump
    
        ;int LineCountParserIndex = 0
        ;int i = StringUtil.Find(CurrentDump, "/delete", LineCountParserIndex)    ; i = EndOfFileFound
    
    ;IF (i == -1)
    ;;    Debug.Trace("SVE_TEST -- Error 02 -- EOF not found!")
    ;    MiscUtil.WriteToFile(s, "/delete", TRUE, False)
    ;ENDIF
    ENDFUNCTION
    
    
    ;--------------
    FUNCTION Main()
    ;--------------
        StartTime = Utility.GetCurrentGameTime()    ; * START TIMER *
    
    ; implement "mic" button
    ; ~~~~~~~~~~~~~~~~~~~~~~
        CurrentDump = myF_GetDump("data/SVE_PI.txt")                ; fills string array with DUMP
    ;;    Debug.Trace("SVE_TEST: has " +DumpLineCount+ " lines (" +CurrentDump+ ")")
        
        string CurrentLine
    ;;;    string CurrentCMD             ; obsolete, instead we use "j" as array command counter
    
    int iCurrentSearchEnd   = 0
    int iCurrentSearchStart = 0
    int i = 1                                                        ; i = LoopCounter
        WHILE (i <= DumpLineCount)
            CurrentLine = myF_GetLine(i)                            ; "GetLine(CurrentDump, LoopCounter, DumpLineCount)"
            int WordsOnCurrentLine = GetNumWords(CurrentLine)
    ;;        Debug.Trace("Number of words on current line: " +WordsOnCurrentLine)
    
            int x = 1                                                ; x = CurrentWordIndex,  (x - 1) = CurrentDumpWordIndex
            WHILE (x <= WordsOnCurrentLine)
                ; Get word y on line x and store word y in array
                s_DA[x - 1] = myF_GetWord(CurrentLine, WordsOnCurrentLine, x)    ; "GetWord(CurrentLine, WordsOnCurrentLine, CurrentWordIndex)"
                x = x + 1
            ENDWHILE
    
    ;;        Debug.Trace("SVE_TEST: Line " +i+ " completed!")
            i = i + 1
        ENDWHILE
    ;    ----------------------------------------
        Debug.Notification("SVE DUMP COMPLETE.")
    ;    ----------------------------------------
        i = 1
        WHILE (i <= DumpLineCount)
    ;;        Debug.Trace("Loop " +i+ " of " + DumpLineCount)
    
            int j = 0                                                ; j = FindCommandCounter
            WHILE (j <= 7)                                            ; 8 commands for now
    ;            -----------------------------------------------------------
                Debug.trace("Searching for command " + s_CMD[j] + " beginning in SVE_Dump at index " +iCurrentSearchStart)
    ;            -----------------------------------------------------------
    ;;            s_CMD[0] = "Thuum"
    ;;            s_CMD[1] = "Equip"
    ;;            s_CMD[2] = "Unequip"
    ;;            s_CMD[3] = "Use"
    ;;            s_CMD[4] = "Cast"
    ;;            s_CMD[5] = "Map"
    ;;            s_CMD[6] = "Save"
    ;;            s_CMD[7] = "Exit"
    
                int iCMDFound = s_DA.Find(s_CMD[j], iCurrentSearchStart)
    ;            -----------------------------------------------------------
                Debug.Trace("SVE_TEST: Searching for executable command at position " +j)
    ;            -----------------------------------------------------------
    
                IF (iCMDFound >= 0)                                     ; this cycles through the command form list (e.g. equip, use, cast, thuum, etc)
    ;;;                CurrentCMD = s_DA[iCMDFound]
    ;;;                Debug.Trace("Command found: " + s_DA[iCMDFound] + " in index " + iCMDFound)
    
                    IF     (j == 0)        ; "Thuum"
                        ;search next three indices for thuum words against Thuum formlist
                        ;do all three words belong to the same thuum?
                        ;how many words does the player know?
                        ;shout
    ;                ---------------------------
                    ELSEIF (j == 3)        ; "Use"
                        ;potion formlist
    ;                ----------------------------
                    ELSEIF (j == 4)        ; "Cast"
                        ;spell formlist
    ;                ---------------------------
                    ELSEIF (j == 5)        ; "Map"
                        ;int MapKey = Input.GetMappedKey("Quick Map",0x00)
                        ;Input.TapKey(MapKey)
    ;                ----------------------------
                    ELSEIF (j == 6)        ; "Save"
                        ;int SaveKey = Input.GetMappedKey("Quicksave",0x00)
                        ;Input.TapKey(SaveKey)
    ;                ----------------------------
                    ELSEIF (j == 7)        ; "Exit"
                        ;Debug.QuitGame()
    ;                -------------------------------
                    ELSEIF (j == 2)     ; "Unequip"
                        ;iCurrentSearchEnd = myF_UnEquip()
    ;                -----------------------------
                    ELSEIF (j == 1)        ; "Equip"
                        iCurrentSearchEnd = myF_CMD_Equip(iCMDFound)        
                    ENDIF
                ENDIF
        
                j = j + 1
            ENDWHILE
    ;        -----------------------------------------------------------
            Debug.Trace("SVE_TEST: Updating variables for main loop..")
    ;        -----------------------------------------------------------
            iCurrentSearchStart = iCurrentSearchEnd                        ; endCMD
            i = i + 1
        ENDWHILE
    
    ; #############
        Debug.Trace("SVE_TEST: Command parser test complete in " + (Utility.GetCurrentGameTime() - StartTime) + " seconds.")
        Debug.Notification("Dumping SVE_Dump to Log")
    
        i = 0
        WHILE (i <= 13)
            Debug.Trace("SVE_TEST: word " +i+ " " +s_DA[i])
            i = i + 1
        ENDWHILE
    ; #############
    ENDFUNCTION
    
    
    ;---------------------------------
    String FUNCTION myF_GetLine(Int n)                                                
    ;---------------------------------
    ;String FUNCTION GetLine(string SVE_PO,int CurrentLineNumber,int NumberOfLines)        ; was called by "GetLine(CurrentDump, LoopCounter, DumpLineCount)"
    ; *******************************************************************************
    ; *** I assume string "CurrentDump" has been declared on top as heap variable ***
    ; *******************************************************************************
    
        n = n - 1                                                ; n = LinesToSkip
        int LineStartIndex = 0
        
    string s                                                    ; s = LineReturn
    int i = 0                                                    ; i = LinesSkipped
        WHILE (i <= n)
            int NullCharIndex = StringUtil.Find(CurrentDump, "/n", LineStartIndex)
    
            IF (NullCharIndex != -1)
                s = StringUtil.Substring(CurrentDump, LineStartIndex, NullCharIndex - LineStartIndex)
                LineStartIndex = NullCharIndex + 2
                i = i + 1
            ENDIF
        ENDWHILE
    
        RETURN s    
    ENDFUNCTION
    
    
    ;-----------------------------------------------------------
    String FUNCTION myF_GetWord(String sLine, Int iWords, Int n)
    ;-----------------------------------------------------------
    ;String FUNCTION GetWord(String SVE_CurrentLine, int WordsOnLine, int WordNumber)    ; was called by "GetWord(CurrentLine, WordsOnCurrentLine, CurrentWordIndex)"
    
        n  = n - 1                     ; n = WordsToSkip // this is incorrect e.g. on the first pass wordsonline==8, and wordnumber==1, but will skip 7 words.
        int WordStartIndex = 0                                    ; WordStartIndex = WordParserStart
        
    string s                                                    ; s = WordReturn
    int i = 0                                                    ; i = WordsSkipped
        WHILE (i <= n)
            int EndSpaceIndex = StringUtil.Find(sLine," ", WordStartIndex) ; EndSpaceIndex = EndOfWord // accounting for space
    
            IF (EndSpaceIndex != -1)
                s = StringUtil.Substring(sLine, WordStartIndex, EndSpaceIndex - WordStartIndex)
                WordStartIndex = EndSpaceIndex + 1
                i = i + 1
            ENDIF
        ENDWHILE
        
        RETURN s
    ENDFUNCTION
    
    
    ;---------------------------------
    Int FUNCTION GetNumWords(String s)
    ;---------------------------------
    ;int function GetNumWords(string SVE_CurrentLine)                                    ; was called by "GetNumWords(CurrentLine)"
    ;;;    int NullCharIndex = StringUtil.Find(s, "/n", 0)            ; UnUSED // Finds index of null character/end of line, start with zero
    
        int WordBeginningIndex = 0                                 ; index: beginning of the word
        int SpaceIndex         = 0                                ; index: end of the word
    
    int i = 0                                                    ; i = WordCount
        WHILE (SpaceIndex != -1)
            SpaceIndex = StringUtil.Find(s, " ", WordBeginningIndex)        ; " word1 ", "word2 "
            IF (SpaceIndex != -1)
                WordBeginningIndex = SpaceIndex + 1
                i = i + 1
            ENDIF
        ENDWHILE
    
        RETURN i        ; number of words on the current line
    ENDFUNCTION
    
    
    ;-----------------------------------
    Int FUNCTION myF_CMD_Equip(Int iCMD)
    ;-----------------------------------
    ; iCMD = iCMDFound
    
    ; declarations out of loop
    ; ~~~~~~~~~~~~~~~~~~~~~~~~
        string[] a = new String[10]                                ; a = Formulator
    
    ;;;    string MaterialType
    ;;;    string WeaponType
    ;;;    string WeaponName
    ;;;    string ArmorType
    ;;;    string ArmorName
    
    ;;;    string ItemFound
        string s                                                ; s = iToParse // need to rename this, NOW it is!
    
        bool break = False
    
        int endCMD     = s_DA.Find("QUICK", iCMD)                ; try to find the string "QUICK" at position iCMDFound, return this value at the end
        int iCMDLength = endCMD - iCMD
    
        ; *** THIS LOOP IS NOT PERFECT !!! ***    
    
    int i                                                        ; i = iItemFound
    int c = 0                                                    ; c = CMDParserCounter
        WHILE (c <= iCMDLength) && (!break)
    
            s = s_DA[iCMD + c]
    ;;        Debug.Trace("SVE_TEST: myF_CMD_Equip() - (" +s+")")
    ;        --------------------
            IF (!break) && (s_Material.Find(s) >= 0)
                break = TRUE
                a[0] = s_DA[iCMD + c]                            ; [0] MaterialType
                debug.trace("Material type detected at " + c)
            ENDIF
    ;        --------------------
            IF (!break) && (s_Weapon.Find(s) >= 0)
                break = TRUE
                a[1] = s_DA[iCMD + c]                            ; [1] WeaponType
                debug.trace("Weapon type detected at " + c)
    
                IF (sn_Weapon.Find(s) >= 0)
                    a[2] = s_DA[iCMD + c]                        ; [2] WeaponName
                    debug.trace("Unique weapon modifier detected at " + c)
                ENDIF
            ENDIF
    ;        --------------------
            IF (!break) && (s_Armor.Find(s) >= 0)
                break = TRUE
                a[3] = s_DA[iCMD + c]                            ; [3] ArmorType
                debug.trace("Armor type detected at " + c)
    
                IF (sn_Armor.Find(s) >= 0)
                    a[4] = s_DA[iCMD + c]                        ; [4] ArmorName
                    debug.trace("Unique armor modifier detected at " + c)
                ENDIF
            ENDIF
    ;        --------------------
            IF (!break)
                Debug.Trace("SVE_TEST: nothing found..")
                c = iCMDLength        ; /// BREAK the loop ///
            ENDIF
                            
            c = c + 1
        ENDWHILE
    
    ; ==========================
        IF ( a[0] )
                s = a[0]        ; Material
        ENDIF
    
         IF ( a[1] )
                s+= " " + a[1]    ; Weapon type
            
            IF ( a[2] )
                s+= " " + a[2]    ; Weapon name
            ENDIF
        ENDIF
    
         IF ( a[3] )
                 s+= " " + a[3]    ; Armor type
            
            IF ( a[4] )
                s+= " " + a[4]    ; Armor name
            ENDIF
        ENDIF
    
    ;;;    a[5] = a[0]+" "+a[1]+" "+a[2]+" "+a[3]+" "+a[4]
        Debug.Trace("SVE_TEST: " +s)
                                        
        ;weapon or armor?
    
    ;armor/clothing
        ;should look for keywords like armor, breastplate, helmet, boots, gauntlets, cloaks, etc.
        ;this will be called piece
        ;modifier type will be called piecetype, this will be mostly materials
        ;expecting form "equip ebony armor", "equip dragonbone helmet", etc
                        
    ;weapon
        ;name (staff of magus)    
        ;material
        ;type (e.g. dagger, sword, greatsword, staff, bow, gloves)
    
    ;equipping hand
        ;expecting form "ebony bow and arrows", "or ebony bow and ebony arrows"
        ;expecting form "equip dragonsting dagger in left hand"
        ;expecting form "equip staff of magus in right hand", etc.
    
        RETURN endCMD        ; see above code line "endCMD = s_DA.Find("QUICK", iCMD)"
    ENDFUNCTION

     

     

  3. Maybe the following script could be useful. It's different to your source.

     

    Scriptname _Follower20P extends ActiveMagicEffect  
    {rewritten by ReDragon 2016}
    
      Spell       PROPERTY Voicecallsofia     auto        ; the follower will cast if under 20% health
    
     ;Spell       PROPERTY FollowerSummon     auto        ; the spell you cast or the ability the follower should have
      MagicEffect PROPERTY MGE_FollowerSummon auto        ; the magicEffect of this script
     
      Float PROPERTY waitTimer auto                       ; fill with your desired time
    
      Actor target                                        ; for speed and make persistent
      Float fHealth                                       ; take it out of event
     
    
    ; **********************************************************************
    ; You wrote: "My aim was to force a follower to summon another character
    ;             when her health had dropped below 20% during combat."
    ; **********************************************************************
    
    ; -- EVENTs -- 3 + "Waiting"
    
    ; Event received when this effect is first started (OnInit may not have been run yet!)
    EVENT OnEffectStart(Actor akTarget, Actor akCaster)
        Debug.Trace("Summon: OnEffectStart() - target = " +akTarget+ ", caster = " +akCaster)       ; remove this line if you do not need it anymore
    
    IF akTarget.HasMagicEffect(MGE_FollowerSummon) || !akTarget.IsPlayerTeammate()
        self.Dispel()
        RETURN    ; - STOP -    follower already has this magiceffect or is not by your side
    ENDIF
    ;---------------------
        target = akTarget        ; == self.GetTargetActor()
    ENDEVENT
    
    
    ; Event received when this effect is finished (effect may already be deleted, calling functions on this effect will fail)
    EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
        Debug.Trace("Summon: OnEffectFinish() - target = " +akTarget+ ", caster = " +akCaster)   ; a bit info, remove the whole event if all is fine
    ;;;    target = None        ; use with caution !!!
    ENDEVENT
    
     
    EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
    IF (akAggressor as Actor) && (target)
    ELSE
        RETURN    ; - STOP -    safety first
    ENDIF
    ;---------------------
        fHealth = target.GetAVPercentage("Health")
    
    IF (fHealth > 0.2)
        RETURN    ; - STOP -    health is higher than 20%
    ENDIF
    ;---------------------
        gotoState("Waiting")            ; ### STATE ### go out of empty state until OnUpdate() is running
        myF_Cast()
        RegisterForSingleUpdate(120.0)                                          ; 2 min, summoned creature should be max alive, casting cool down
        Utility.Wait(waitTimer)                                                 ; wait until idle is over, which is running on the follower
    ENDEVENT
    
    
    FUNCTION myF_Cast()
    ;------------------
    IF ( target )
        Debug.SendAnimationEvent(target as ObjectReference, "Shout Start")      ; let the follower doing a special idle, hopefully the right string
        voicecallsofia.Cast(target as ObjectReference, None)                    ; follower is casting the summon spell
    ENDIF
    ENDFUNCTION
    
    
    ;==========================
    state Waiting    ; already Waiting
    ;============
    EVENT OnUpdate()
    IF (target) && target.Is3DLoaded()
        gotoState("")                    ; ### STATE ###    go back to empty state, OnHit() above is available again
    ENDIF
    ENDEVENT
    
    EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
    ENDEVENT
    ;=======
    endState

     

     

  4. There seems to be the same issue you'll find here:
    https://www.reddit.com/r/skyrimmods/comments/3urz2r/crashing_with_perkus_maximus_during_combat/

    Your papyrus logfile has a lot of such entries.

     


    [11/07/2016 - 01:43:56PM] error: Cannot call HasPerk() on a None object, aborting function call
    stack:
    [Active effect 4 on (00000014)].xMATHICombatLogic.OnHit() - "xMATHICombatLogic.psc" Line 79
    [11/07/2016 - 01:43:56PM] warning: Assigning None to a non-object variable named "::temp3"
    stack:
    [Active effect 4 on (00000014)].xMATHICombatLogic.OnHit() - "xMATHICombatLogic.psc" Line 79

    [11/07/2016 - 01:43:56PM] error: Cannot call HasPerk() on a None object, aborting function call
    stack:
    [Active effect 4 on (00000014)].xMATHICombatLogic.OnHit() - "xMATHICombatLogic.psc" Line 81
    [11/07/2016 - 01:43:56PM] warning: Assigning None to a non-object variable named "::temp6"
    stack:
    [Active effect 4 on (00000014)].xMATHICombatLogic.OnHit() - "xMATHICombatLogic.psc" Line 81


    This crazy script is a part of

    Mod: "T3nd0's Perkus Maximus" by T3nd0
    http://www.nexusmods.com/skyrim/mods/59849/?

    filename: Perkus Maximus 1-6-4

     

    The Script, which is gone wild, has that source file a bit changed for documentation:

     

     

    Scriptname xMATHICombatLogic extends activemagiceffect  
    
    perk property xmaDexRemovingTheScaffold auto
    perk property xmaDexMonkeyGrip auto
    perk property xmaLIAEndeavor0 auto
    perk property xmaLIAEndeavor1 auto
    
    spell property xMALIAEndeavor0Spell Auto
    spell property xMALIAEndeavor1Spell Auto
    
    FormList Property xMADEXDontStealFormList Auto
    keyword property xmaweaptypefist auto
    
    actor target = none
    
    State busy
        Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
        EndEvent
    EndState
    
    Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
        gotoState("busy")
        
        actor att = (akAggressor as actor)
        Weapon w = aksource as weapon
    
        if att && w && w.hasKeyword(xmaweaptypefist)
            ;; monkey grip
    
            if att.hasperk(xmadexmonkeygrip) && abHitBlocked
                armor shield = target.getEquippedShield()
    
                If (shield) &&  !(xMADEXDontStealFormList.hasForm(shield))
                        target.unequipItem(shield, false)
                        target.removeitem(shield,1)
                        att.additem(shield,1)
                endif
            endif
    
            ;; removing the scaffold
    
            if att.hasperk(xmadexremovingthescaffold) && !abHitBlocked
                ;it looks like Helmet and Gantlets are not in correct slots.
                ;Its better to add these lines of code instead of replacing the old ones.
                ;This way we are sure this will always work
                Armor arms = target.GetWornForm(0x00000010) as armor    ; Forearms        GetWornForm() is a SKSE function
                if !arms
                    arms = target.GetWornForm(0x00000008) as armor      ; Hands
                endif
                Armor helm = target.GetWornForm(0x00000001) as armor    ; Head
                if !helm
                    helm = target.GetWornForm(0x00000002) as armor        ;Hair
                endif
                Armor leg = target.GetWornForm(0x00000080) as armor
                Armor body = target.GetWornForm(0x00000004) as armor
    
                if arms &&  !(xMADEXDontStealFormList.hasForm(arms))
                    target.unequipItem(arms, false)
                    target.removeitem(arms,1)
                    att.additem(arms,1)
                elseif helm &&  !(xMADEXDontStealFormList.hasForm(helm))
                    target.unequipItem(helm, false)
                    target.removeitem(helm,1)
                    att.additem(helm,1)
                elseif leg &&  !(xMADEXDontStealFormList.hasForm(leg))
                    target.unequipItem(leg, false)
                    target.removeitem(leg,1)
                    att.additem(leg,1)
                elseif body &&  !(xMADEXDontStealFormList.hasForm(body))
                    target.unequipItem(body, false)
                    target.removeitem(body,1)
                    att.additem(body,1)
                endif
            endif
        endif
    
        if !abHitBlocked
            if target.hasperk(xMAliaEndeavor1)             ; error line 79, target can be <None> caused by effect finish
                xMAliaEndeavor1Spell.cast(target, target)
            elseif target.hasperk(xMAliaEndeavor0)         ; error line 81, target can be <None> caused by effect finish
                xMAliaEndeavor0Spell.cast(target, target)
            endif
        endif
        gotoState("")
    EndEvent
    
    
    ;EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    Event OnEffectStart(actor t, actor c)
        target = t
    EndEvent
    
    ;EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    Event OnEffectFinish(actor t, actor c)
        target = none                             ; IF magic effect has been finished target becomes <None>
    EndEvent

     

     

     

    What should you do?

    The only way is to rewrite the script "xMATHICombatLogic.psc" to make sure errors can be gone.

    Unfortunately the next patch doesn't work, because the script fix is out of date, it doesn't use a formlist.
    Go to the file page from Perkus Maximus mod and look at "Script fix", download the archive.

    You have to clean your savegame and mod order.

    1. Remove all these mod files which are related to "PerMa".

    PerkusMaximus_Master.esp=1
    PerkusMaximus_Warrior.esp=1
    PerkusMaximus_Thief.esp=1
    PerkusMaximus_Mage.esp=1
    PerMa Expansion 1 - Wintermyst.esp=1
    PatchusMaximus.esp=1
    PerMa_USKP master patch.esp=1
    ISC PerMa Compatibility Patch.esp=1


    2. Make sure you don't have any loose file in your Skyrim installation which was a part of mods from above.
    If you had installed with nexus mod manager it shouldn't be. If not that files are
    meshes (*.nif), textures (*.dds), papyrus scripts (*.pex) and java specific files (xml, class, jar).

    3. Use the next modding tool to clean your savegame!

    Mod: "Save game script cleaner" v2.06 by Hadoram
    http://www.nexusmods.com/skyrim/mods/52363/?


    4. Your load order is strange, should be look like this:

    Skyrim.esm=1
    Update.esm=1
    Dawnguard.esm=1
    HearthFires.esm=1
    Dragonborn.esm=1
    ApachiiHair.esm=1
    Skyrim Project Optimization - Full Version.esm=1
    SkyMoMod.esm=1
    Unique Flowers & Plants.esm=1
    MagicDuelReborn.esm=1 ; Do you really need that?
    JSwords.esm=1
    RSkyrimChildren.esm=1
    CompanionArissa.esm=1
    hdtHighHeel.esm=1
    Unofficial Skyrim Legendary Edition Patch.esp=1
    HighResTexturePack01.esp=1
    HighResTexturePack02.esp=1
    HighResTexturePack03.esp=1
    Unofficial High Resolution Patch.esp ; missing mod file !!
    ..
    SleepingDangers-SandsofTime.esp=1
    notice board.esp=1
    ..
    Alternate Start - Live Another Life.esp=1 ; Do you really need that?
    ..
    Skyrim Immersive Creatures.esp=1
    Skyrim Immersive Creatures - DLC2.esp=1
    ..
    Rebirth Monster.esp=1 ; Do you really need that?


    Maybe it helps to make your Skyrim more stabile!

  5. You wrote:

    I'm having the same exact issue. After installing WICO for SSE, I immediately had a grey face for a majority of the NPCs.

     

    Mod: WICO - Windsong Immersive Character Overhaul by Windsong
    http://www.nexusmods.com/skyrimspecialedition/mods/2136/?

    Did you ever read the sticky post with headline [ Dark Face Issue ]?

    Ok.. What is happen with grey faces?
    If you click on the files section, you'll see behind of each downloadable version an icon like a magnifying glass.

    Click on this icon to see what is the archive structure. Folder no. 11 is called "Main - core Files".
    This folder has some bsa-files inside. Each of this is an archive similiar to zip or 7z, but in new ba2-file format
    which is different in Skyrim SE to older Skyrim.

    In case current version of NexusModManager has trouble to read this archive format, you could have grey face bug.

    Another explanation and more likely could be as follow:

    Let us assume inside these bsa-archives are facegen data, path like that:
    "C:\Program Files (x86)\Steam\steamapps\common\Skyrim Special Edition\Data\meshes\actors\character\FaceGenData\FaceGeom\WICO - Immersive Character.esp"

    and you built handmade facegen data, path like that:
    "C:\Program Files (x86)\Steam\steamapps\common\Skyrim Special Edition\Data\meshes\actors\character\FaceGenData\FaceGeom\Skyrim.esm"

    Who will win the race of facegen data?
    It's always the last loaded file.

    - It depends on the mod load order (.esm/.esp) if the last file is inside the bsa-archive

    - or if exists the file on your Skyrim installation drive.

    But keep in mind if you change any facegen data of NPC you have to make sure
    - the right mesh files *.NIF -- 000918E2.nif
    - the right texture file *.DDS -- 000918E2.dds
    have to be loaded for that modified NPC.

    In case mesh and texture do not fit with modification, you'll see grey or black face for that NPC.

    In good old Skyrim there is a folder structure like that (X is any drive number, you installed Skyrim):

    for meshes

    "X:\Steam\SteamApps\common\skyrim\Data\meshes\actors\character\FaceGenData\FaceGeom\Skyrim.esm" <- vanilla path
    "X:\Steam\SteamApps\common\skyrim\Data\meshes\actors\character\FaceGenData\FaceGeom\myMod.esp" <- mod path like mod name

    for textures

    "X:\Steam\SteamApps\common\skyrim\Data\textures\actors\character\FaceGenData\FaceTint\Skyrim.esm" <- vanilla facegen textures path
    "X:\Steam\SteamApps\common\skyrim\Data\textures\actors\character\FaceGenData\FaceTint\myMod.esp" <- mod path like meshes above

    No solution, but an explanation to think about facegen issue.

  6. Maybe next adjusted wiki script could be helpful to understand what the original script is doing. Not all wiki scripts are really handy to modify!

    ScriptName RepeatableSummonEffectScript extends ActiveMagicEffect
    {rewritten by ReDragon 2016, source: http://www.creationkit.com/index.php?title=Complete_Example_Scripts}
    
      Actor           PROPERTY YourSummonREF auto    ; fill with an existing actor
     ;ObjectReference PROPERTY YourSummonREF auto    ; will also work with the summon function
    
      Activator PROPERTY SummonTargetFXActivator auto  ; fill with activtor which has FormID "0x0007CD55"
    
    
    ; -- EVENTs -- 2
    
    EVENT OnEffectStart(Actor akTarget, Actor akCaster)
        Debug.Trace("SummonEffectScript: OnEffecStart() - caster = " +akCaster+", target = " +akTarget+"  " +self)    ; a bit information about runtime
        Summon(akCaster, YourSummonREF as ObjectReference)
    ENDEVENT
    
    EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
        Debug.Trace("SummonEffectScript: OnEffectFinish() - caster = " +akCaster+", target = " +akTarget)
    ENDEVENT
    
    
    ; -- FUNCTION --
    
    ;-------------------------------------------------------------------------------------------------------
    FUNCTION Summon(Actor akSummoner, ObjectReference akSummon, Float afDistance=150.0, Float afZOffset=0.0)
    ;-------------------------------------------------------------------------------------------------------
    IF (akSummoner) && (akSummon) && (SummonTargetFXActivator)
    ELSE
        RETURN    ; - STOP -    akCaster is <None> OR YourSummonREF is <None>
    ENDIF
    ;---------------------
    ; Shroud summon with portal                     aiStage == 1
    ;;    ObjectReference Function PlaceAtMe(akFormToPlace, aiCount=1, abForcePersist=False, abInitiallyDisabled=False) native
    
    ;;;    objectReference arPortal = akSummon.PlaceAtMe(Game.GetForm(0x0007CD55), 1, False, False)         ; "arPortal" is non-peristent placed a SummonTargetFXActivator
        objectReference arPortal = akSummon.PlaceAtMe(SummonTargetFXActivator as Form, 1, False, False)    ; same as above but is using a property
        Utility.Wait(0.6)
    
    ; -----------------------------------------
    ; Disable Summon                                aiStage == 2
        akSummon.Disable()        ; switch OFF
        Utility.Wait(0.25)
    
    ; -----------------------------------------
    ; Move portal in front of summoner              aiStage == 3
        float f = akSummoner.GetAngleZ()
        arPortal.MoveTo(akSummoner as ObjectReference, (Math.Sin(f) * afDistance), (Math.Cos(f) * afDistance), afZOffset)
        Utility.Wait(0.5)
    
    ;------------------------------------------
    ; Move summon to portal                         aiStage == 4
        akSummon.MoveTo(arPortal)
        Utility.Wait(0.25)
     
    ;------------------------------------------
    ; Enable summon as the portal dissipates        aiStage == 5
        akSummon.Enable()        ; switch ON
    ;;;    Utility.Wait(0.6)
    
    ; SummonTargetFXActivator disables and deletes itself, if this function finished (shortly after stage 5) hopefully
    ENDFUNCTION
  7. Answers to steve40:

     

    : "Unfortunately it is still possible for objects to unload in between calling is3DLoaded() and PlayAnimation(), so I anticipate that errors will still sneak into the logs occasionally."

    PlayAnimation is not the culprit, the code line "mySFX.play(self)" is the the troublemaker and this is strong protected by conditions.

     

    : "Your myF_Dust() function is a bit unnecessarily complicated though! Note that it is unnecessary to delete the explosion effect, as explosions self-delete automatically."

    Sure.. a non-persistent objectReference should be deleted automatically. But why not doing it, if we have the control about the objectReference.

     

    : ".. could have been ignored if you had used GetFormFromFile rather than GetForm"

    I used this construct to show, how to detect DLCs or other Mods without papyrus log spam. The using of leading byte makes the code more comfortable imho.

     

    : "Lastly, I've updated the list of FormIDs in my original post. I had a couple of typos, I missed a couple of forms, plus I've added FormIDs for the two effects added by Dragonborn DLC03."

    I'm sorry, my first approach I made 1.5 year ago. I have never seen your adjustments or Dragonborn edits. Nevertheless with my second approach it's unnecessary to know where is the cell or what is the FormID of the cell. Eventually endless stack loops clean up with 1 error in papyrus log file.

     

    : "I should also mention that USKP/USLEEP already includes a fix for fxDustDropRandomSCRIPT afaik."

    Yes, you're right USKP is fixing the vanilla script. But I'm not sure about the using of OnUpdate() in the USKP scripts.

     

    : "I would hope that by now people would be using those patches before beginning a new game and therefore not requiring our script fixes."

    Hmm..

×
×
  • Create New...