Genamine Posted February 27, 2017 Share Posted February 27, 2017 Lets say I have some FormLists FormList A with a list of 3 perksFormList B with sub-FormLists C, D and EFormList C, D and E with a list of actors Now, what Im trying to do is run a loop that adds the perk at a certain index on FormList A to all sub-FormLists on FormList B with the same index as the belonging perkSo.. perk 1 will go with FormList C, perk 2 will go with FormList D and perk 3 will go with FormList E This requires some variables, ofcourse, lets presume: Perk Property RegisteredPotentialPerk Auto RegisteredPotentialPerk = PotentialPerkList.GetAt(iFormsToRun) as Perk Question 1: Would this be a working set of variables? Now, to continue, we want to add these perks to an actor from the other FormLists, lets presume: Int iIndex = RegisteredActorList.GetSize() While iIndex > -1 Actor akActor = RegisteredActorList.GetAt(iIndex) as Actor If akActor.HasPerk(RegisteredPotentialPerk) == 0 akActor.AddPerk(RegisteredPotentialPerk) EndIf iIndex -= 1 EndWhile Question 2: Is this a functioning fragment of code? Now, to end with, I obviously wouldnt be asking this if it was actually workingSee, the thing is, after some debugging I found that everything works as intended, it compiled, all statements conditions and functions pass just fine, but the perks are not being applied as expectedWhich makes me wonder if calling [RegisteredPotentialPerk = PotentialPerkList.GetAt(0) as Perk] actually works or not, does this not set the property as a perk?, does this still remain a Form? Its a bit of a problem for me right now, because I find a script preferable over adding perks to just under 1200 actors by hand For those interested, here is the full script, its only a little more complex than shown fragments: Scriptname AddPerksOnLaunch extends Quest FormList Property PotentialPerkList Auto Const FormList Property ActorList Auto Const Bool Property HardMode Auto Const FormList Property RegisteredActorList Auto Perk Property RegisteredPotentialPerk Auto Function RunForFormList() Int iIndex = RegisteredActorList.GetSize() While iIndex > -1 Actor akActor = RegisteredActorList.GetAt(iIndex) as Actor If akActor.HasPerk(RegisteredPotentialPerk) == 0 akActor.AddPerk(RegisteredPotentialPerk) EndIf iIndex -= 1 EndWhile EndFunction Event OnInit() Utility.Wait(10) Int iFormsToRun = PotentialPerkList.GetSize() While iFormsToRun > -1 RegisteredActorList = ActorList.GetAt(iFormsToRun) as FormList If PotentialPerkList.GetAt(iFormsToRun) as FormList Actor akPlayerActor = RegisteredActorList.GetAt(0) as Actor Perk kPerk01 = PotentialPerkList.GetAt(0) as Perk Perk kPerk02 = PotentialPerkList.GetAt(1) as Perk Perk kPerk03 = PotentialPerkList.GetAt(2) as Perk If HardMode == True Perk kPerk04 = PotentialPerkList.GetAt(3) as Perk If akPlayerActor.HasPerk(kPerk04) == 0 akPlayerActor.AddPerk(kPerk04) EndIf EndIf If akPlayerActor.HasPerk(kPerk01) == 0 akPlayerActor.AddPerk(kPerk01) EndIf If akPlayerActor.HasPerk(kPerk02) == 0 akPlayerActor.AddPerk(kPerk02) EndIf If akPlayerActor.HasPerk(kPerk03) == 0 akPlayerActor.AddPerk(kPerk03) EndIf ElseIf PotentialPerkList.GetAt(iFormsToRun) as Perk RegisteredPotentialPerk = PotentialPerkList.GetAt(iFormsToRun) as Perk RunForFormList() EndIf iFormsToRun -= 1 EndWhile EndEvent Link to comment Share on other sites More sharing options...
kitcat81 Posted February 28, 2017 Share Posted February 28, 2017 It`s a bit complicated with so many formlists :D. You can try to look at debug log . Use usual text search to find anything that has something to do with your script name. If there are any errors that abort some of the functions it will show them. You need to enable debug log for this. What I can see from looking at it is that you use getsize() and then you use this size as an index for getat() If I understand the work of these things correct then , for example, a formlist that has size = 5 does not have position number 5. So you can`t use getat(5) . It has positions 0, 1, 2, 3, 4So you probably need to type GetAt(Index -1) , or type in the beginning Int iIndex = RegisteredActorList.GetSize() - 1 , or move the line iIndex -= 1 upper so it runs before the getat() This is a simple good example from wiki of using while with formlist. iTndex -= 1 runs before the GetAt() so it never gets at the position equal to the size. It starts from the position = size -1 Int iIndex = akList.GetSize() ; Will always return a finite value While iIndex > 0 iIndex -= 1 If akList.GetAt(iIndex) == akMember Return iIndex EndIf EndWhile Link to comment Share on other sites More sharing options...
Genamine Posted February 28, 2017 Author Share Posted February 28, 2017 It`s a bit complicated with so many formlists :D. You can try to look at debug log . Use usual text search to find anything that has something to do with your script name. If there are any errors that abort some of the functions it will show them. You need to enable debug log for this. What I can see from looking at it is that you use getsize() and then you use this size as an index for getat() If I understand the work of these things correct then , for example, a formlist that has size = 5 does not have position number 5. So you can`t use getat(5) . It has positions 0, 1, 2, 3, 4So you probably need to type GetAt(Index -1) , or type in the beginning Int iIndex = RegisteredActorList.GetSize() - 1 , or move the line iIndex -= 1 upper so it runs before the getat() This is a simple good example from wiki of using while with formlist. iTndex -= 1 runs before the GetAt() so it never gets at the position equal to the size. It starts from the position = size -1 Int iIndex = akList.GetSize() ; Will always return a finite value While iIndex > 0 iIndex -= 1 If akList.GetAt(iIndex) == akMember Return iIndex EndIf EndWhile Thats the original syntax I used, but it had the same problem as the current one, everything runs as it should, trial and error shows that it gets to the akActor.AddPerk() line just fine, but it doesnt actually apply the perk EDIT: small update from looking at the papyrus log, it says cannot call HasPerk() and AddPerk() on a none object, as well as warning: Assigning None to a non-object variable named "::temp27"So it must be going wrong at Actor akActor = RegisteredActorList.GetAt(iIndex) as Actor Debugging the properties results in the following, Debug.Trace(akActor) returns "None", Debug.Trace(RegisteredPotentialPerk) returns "[Perk < (0D340A85)>]", which is correctDebug.Trace(RegisteredActorList.GetAt(iIndex)) returns the correct form of the actor(s) the perk is to be applied to, it appears that calling "as Actor" sets the value to "None" Link to comment Share on other sites More sharing options...
Genamine Posted February 28, 2017 Author Share Posted February 28, 2017 Little addition to previous post: Heres the script with added debug lines: Scriptname AddPerksOnLaunch extends Quest FormList Property PotentialPerkList Auto Const FormList Property ActorList Auto Const Bool Property HardMode Auto Const FormList Property RegisteredActorList Auto Perk Property RegisteredPotentialPerk Auto Bool Property CurrentlyRunning Auto Function RunForFormList() CurrentlyRunning = True Int iIndex = RegisteredActorList.GetSize() Debug.Trace(iIndex) While iIndex > -1 iIndex -= 1 Debug.Trace(iIndex) Form kActorForm = RegisteredActorList.GetAt(iIndex) Actor akRegisteredActor = kActorForm as Actor Debug.Trace(kActorForm) If kActorForm as Actor Debug.Trace("Form is type Actor.") Else Debug.Trace("Form is not type Actor.") EndIf Debug.Trace(akRegisteredActor) If akRegisteredActor != None If akRegisteredActor.HasPerk(RegisteredPotentialPerk) == 0 Debug.Trace("Actor returned, did not have perk, applying perk now.") akRegisteredActor.AddPerk(RegisteredPotentialPerk) Else Debug.Trace("Actor returned, already had perk, will not proceed.") EndIf Else Debug.Trace("Actor returned none, will not proceed.") EndIf EndWhile CurrentlyRunning = False EndFunction Event OnInit() Utility.Wait(10) Int iFormsToRun = PotentialPerkList.GetSize() While iFormsToRun > -1 Utility.Wait(1) If CurrentlyRunning == False iFormsToRun -= 1 RegisteredActorList = ActorList.GetAt(iFormsToRun) as FormList If PotentialPerkList.GetAt(iFormsToRun) as FormList Actor akPlayerActor = Game.GetPlayer() Perk kPerk01 = PotentialPerkList.GetAt(0) as Perk Perk kPerk02 = PotentialPerkList.GetAt(1) as Perk Perk kPerk03 = PotentialPerkList.GetAt(2) as Perk If HardMode == True Perk kPerk04 = PotentialPerkList.GetAt(3) as Perk If akPlayerActor.HasPerk(kPerk04) == 0 akPlayerActor.AddPerk(kPerk04) EndIf EndIf If akPlayerActor.HasPerk(kPerk01) == 0 akPlayerActor.AddPerk(kPerk01) EndIf If akPlayerActor.HasPerk(kPerk02) == 0 akPlayerActor.AddPerk(kPerk02) EndIf If akPlayerActor.HasPerk(kPerk03) == 0 akPlayerActor.AddPerk(kPerk03) EndIf ElseIf PotentialPerkList.GetAt(iFormsToRun) as Perk RegisteredPotentialPerk = PotentialPerkList.GetAt(iFormsToRun) as Perk Debug.Trace(RegisteredActorList) Debug.Trace(RegisteredPotentialPerk) RunForFormList() EndIf EndIf EndWhile EndEvent And heres the result in the papyrus log: [02/28/2017 - 03:01:22PM] [FormList < (0D340A86)>][02/28/2017 - 03:01:22PM] [Perk < (0D340A85)>][02/28/2017 - 03:01:22PM] 265[02/28/2017 - 03:01:22PM] 264[02/28/2017 - 03:01:22PM] [Form < (001167A8)>][02/28/2017 - 03:01:22PM] Form is not type Actor.[02/28/2017 - 03:01:22PM] None[02/28/2017 - 03:01:22PM] Actor returned none, will not proceed. In order, these lines are from:Debug.Trace(RegisteredActorList)Debug.Trace(RegisteredPotentialPerk)Debug.Trace(iIndex) - before loopDebug.Trace(iIndex) - after iIndex -= 1, 264 is indeed the last actor in the FormList, this is where the loop should begin adding perksDebug.Trace(kActorForm)Debug.Trace("Form is not type Actor.")Debug.Trace(akRegisteredActor)Debug.Trace("Actor returned none, will not proceed.") This repeats for the entire FormList, the other debug lines never run It looks like its probably because form Actor is a reference form, while the forms on the FormList are ActorBase, which is a base form, you cant run "as Actor" on those and you cant run HasPerk() or AddPerk() on those In other words, what Im trying to do is probably not even possible Link to comment Share on other sites More sharing options...
kitcat81 Posted February 28, 2017 Share Posted February 28, 2017 (edited) This repeats for the entire FormList, the other debug lines never run It looks like its probably because form Actor is a reference form, while the forms on the FormList are ActorBase, which is a base form, you cant run "as Actor" on those and you cant run HasPerk() or AddPerk() on those In other words, what Im trying to do is probably not even possible oh sorry, maybe I missed something in your script. It`s just the way I saw it was done. But glad that debug helped. Just curious why do you want to add perks to base actors by script(is this even correct? Do you have a list of actors form ID-s) ? You can add perks to base actors in the CK. What exactly do you want to accomplish? Oh, wait I see now , I`m very absent-minded today. 1200 actors...do you want to add perks to all base actors? I never thought that there are so many base actors there. lol I don`t think there is a way to change baseobjects in any way by script. Though you can get some values from them. If you have form ID-s in your list then it`s actorbase objects. Not actors so it won`t work. Edited February 28, 2017 by kitcat81 Link to comment Share on other sites More sharing options...
Genamine Posted February 28, 2017 Author Share Posted February 28, 2017 This repeats for the entire FormList, the other debug lines never run It looks like its probably because form Actor is a reference form, while the forms on the FormList are ActorBase, which is a base form, you cant run "as Actor" on those and you cant run HasPerk() or AddPerk() on those In other words, what Im trying to do is probably not even possible oh sorry, maybe I missed something in your script. It`s just the way I saw it was done. But glad that debug helped. Just curious why do you want to add perks to base actors by script(is this even correct? Do you have a list of actors form ID-s) ? You can add perks to base actors in the CK. What exactly do you want to accomplish? Oh, wait I see now , I`m very absent-minded today. 1200 actors...do you want to add perks to all base actors? I never thought that there are so many base actors there. lol I don`t think there is a way to change baseobjects in any way by script. Though you can get some values from them. If you have form ID-s in your list then it`s actorbase objects. Not actors so it won`t work. I want to add perks to almost 1200 NPCs, multiple perks for manyI was hoping to be able to do so by script so that A - the process is reversible on demand and B - it doesnt conflict with other mods that edit the NPCs in question Sadly it doesnt appear to be a plausible option, I dont believe there is really anything significant you can do to base actors by scriptI know my way around programming, but papyrus is still new to me Link to comment Share on other sites More sharing options...
BlahBlahDEEBlahBlah Posted March 2, 2017 Share Posted March 2, 2017 I fully admit I'm only half reading this. =/...an alternative to perks themselves might be spells that apply the perks. Spells seem to be much easier to apply to base actors (if applying perks is at all possible even, actually), (big) iirc.If you could do it by race, that might even be an alternative to make this process a little more compact.I don't know if I missed it...but what are you trying to apply? A random height change?Anywho...=) Link to comment Share on other sites More sharing options...
Genamine Posted March 2, 2017 Author Share Posted March 2, 2017 I fully admit I'm only half reading this. =/ ...an alternative to perks themselves might be spells that apply the perks. Spells seem to be much easier to apply to base actors (if applying perks is at all possible even, actually), (big) iirc. If you could do it by race, that might even be an alternative to make this process a little more compact. I don't know if I missed it...but what are you trying to apply? A random height change? Anywho...=) Well, as far as Im aware you cant apply spells to base actors by script eitherRace isnt much of an option for me either, I dont want all actors of a certain race to have the same perk What I want to do is apply different perks with different damage modifiers (both conditional and unconditional) to different actors, Id like the process to reversible on-demand ingame (via cqf in console)The first step toward that was to find a way to apply the perks in the first place, and then write a function to remove the perks (and a function to re-add them, should you regret your decision)Sadly though, it doesnt appear to be plausible As far as being able to disable and enable the perks on-demand ingame, Im aware of other (easier) ways to do thisBut applying the perks by script isnt an option, I will instead batch add them to the NPCs with FO4Edit Link to comment Share on other sites More sharing options...
Recommended Posts