-
Posts
640 -
Joined
-
Last visited
Content Type
Profiles
Forums
Events
Posts posted by ReDragon2013
-
-
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
-
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
-
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
-
-
-
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-4The 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! -
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. -
You have loaded the mod "OSA - Skyrim Ascendancy Engine" at hex position 0B, decimal 14 at your Skyrim. s#*! happens..
http://www.nexusmods.com/skyrim/mods/76744/?
Kick it out! Use "Save game script cleaner" by Hadoram
http://www.nexusmods.com/skyrim/mods/52363/?t -
-
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
-
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..
-
-
-
Thank you to steve40 for starting papyrus bug fixing and open my mind for Skyrim weaknesses.
Regards
A bug that makes no sense. Need help please
in Creation Kit and Modders
Posted · Edited by ReDragon2013
..