Macross. Posted August 6, 2018 Posted August 6, 2018 Quick qualifier: While I am not new to programming in general, I have very limited experience with papyrus, so sorry for what I am sure are going to be a lot of nonsensical questions. In short, I have a script from one mod that has an internal function (non global), I would like to add a call to that function inside a script from another mod. But they are scripts working on very different things, so I'm at a loss as to how to get started. The first is the supporting script from Ousnius's weightmorphs mod, which adjusts the player model based on what the player eats. It has a single key function that tracks and changes the "weight" variable that everything else checks to make changes. ScriptName WeightMorphs Extends ReferenceAlias ... ... Function ChangeWeight(Float amount, Bool applyNow = True) Weight = Weight + amount If Weight > MaxWeight Weight = MaxWeight ElseIf Weight < MinWeight Weight = MinWeight EndIf UpdateWeight(applyNow) EndFunction I have another mod that uses a consumption system outside Skyrim's normal eating and drinking mechanics, storing the consumed items until the player uses a "digest" power. I would like to call the above ChangeWeight function on the use of this power so that the digested items can apply the appropriate weightmorphs effects. The problem is this existing script is acting only to extend a magical effect and has no associated quest, so my foolish attempt to call the function in the OnEffectStart event results in a papyrus compiler error saying it needs a reference to work on. Scriptname DigestScript extends activemagiceffect ... ... Event OnEffectStart(Actor akTarget, Actor akCaster) float NoToDigest = NumberInStomach.GetValue() WeightMorphs.ChangeWeight(0.25 * NoToDigest) ... ... EndEvent I've been trying to research a solution, but papyrus is different enough from my previous experience that I'm floundering. So hopefully somebody with more experience can point me in the right direction on what I think is a simple and common occurrence.
Holzfrau Posted August 6, 2018 Posted August 6, 2018 Since the WeightMorphs script attaches to a quest alias, you have to get the specific reference alias you want that is using that script and cast it as a WeightMorphs. What you end up with will probably look something like ([whatever quest uses the WeightMorphs on its aliases].GetAlias([whatever index the player alias is]) as WeightMorphs).ChangeWeight(0.25 * NoToDigest) Since it sounds like this quest is coming out of another mod, you may need to use Game.GetFormFromFile to access it. You could also use GetAliasByName (SKSE) instead of GetAlias; the point is that you have to pull the alias out of the quest somehow.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 Thanks for the response, and again, sorry for some silly questions; I am trying to get away with being lazy and using previous programming experience with a piecemeal understanding of how Skyrim works instead of taking the full dive into everything. 22 minutes ago, Andy14 said: And if your import the WeightMorphs script in DigestScript or set a reference to? As I understand it, that is all I need to do, I'm just not quite clear on how I go about doing either of those steps. The creation kit Wiki provides the following example for using another script as a filled property: myRefAliasScript property refScript auto ;fill this property with your quest in the CK editor ;... refScript.myRefAliasScriptFunction01() refScript.myRefAliasScriptFunction02() ;access two functions that are in the reference alias script Is this what you are referring to? If so, I'm assuming I would insert the first line near the top of the DigestScript, but which parts do I edit and what stays the same? I'm mostly struggling to understand the syntax of the example code; is "myRefAliasScript" a name I get to choose, do I literally type "property" or is that something I need to specify? Further, it mentions filling in a property within the CK quest, but as stated above, the DigestScript doesn't have an associated quest. Can I make an effectively empty script just for this reference alias thing? I believe WeightMorphs does something similar to target the player character reference.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 18 minutes ago, Holzfrau said: Since the WeightMorphs script attaches to a quest alias, you have to get the specific reference alias you want that is using that script and cast it as a WeightMorphs. What you end up with will probably look something like ([whatever quest uses the WeightMorphs on its aliases].GetAlias([whatever index the player alias is]) as WeightMorphs).ChangeWeight(0.25 * NoToDigest) Since it sounds like this quest is coming out of another mod, you may need to use Game.GetFormFromFile to access it. You could also use GetAliasByName (SKSE) instead of GetAlias; the point is that you have to pull the alias out of the quest somehow. Oh, so thats what the whole "as" thing is for. If I know the target alias (just the default player ref) does that simplify things at all? Or is the Alias an independent thing from the associated reference, and particular to the mod's quest?
Holzfrau Posted August 6, 2018 Posted August 6, 2018 2 minutes ago, Synake said: Oh, so thats what the whole "as" think is for. If I know the target alias (just the default player ref) does that simplify things at all? Or is the Alias an independent thing from the associated reference, and particular to the mod's quest? Knowing what the alias is pointing at doesn't get you anywhere because the WeightMorphs script is attached to it through a specific alias on a quest. Access to scripts attached to an alias can only happen "top down" (quest -> alias instead of object instance -> alias) because quest aliases can change during gameplay. So yes, aliases are independent from what they're pointing at, and particular to their containing quest.
Andy14 Posted August 6, 2018 Posted August 6, 2018 13 minutes ago, Synake said: Thanks for the response, and again, sorry for some silly questions; I am trying to get away with being lazy and using previous programming experience with a piecemeal understanding of how Skyrim works instead of taking the full dive into everything. As I understand it, that is all I need to do, I'm just not quite clear on how I go about doing either of those steps. The creation kit Wiki provides the following example for using another script as a filled property: myRefAliasScript property refScript auto ;fill this property with your quest in the CK editor ;... refScript.myRefAliasScriptFunction01() refScript.myRefAliasScriptFunction02() ;access two functions that are in the reference alias script Is this what you are referring to? If so, I'm assuming I would insert the first line near the top of the DigestScript, but which parts do I edit and what stays the same? I'm mostly struggling to understand the syntax of the example code; is "myRefAliasScript" a name I get to choose, do I literally type "property" or is that something I need to specify? Further, it mentions filling in a property within the CK quest, but as stated above, the DigestScript doesn't have an associated quest. Can I make an effectively empty script just for this reference alias thing? I believe WeightMorphs does something similar to target the player character reference. I deleted my post, it was nonsense, since you use a magecieffct. But to answer the question. Import would be like this: Import DigestScript If I understand correctly, NumberInStomach is a global one. Then you can access it in WeightMorphs too.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 6 minutes ago, Holzfrau said: Knowing what the alias is pointing at doesn't get you anywhere because the WeightMorphs script is attached to it through a specific alias on a quest. Access to scripts attached to an alias can only happen "top down" (quest -> alias instead of object instance -> alias) because quest aliases can change during gameplay. So yes, aliases are independent from what they're pointing at, and particular to their containing quest. I was afraid something like that would be the case. Okay, so as you stated above, since the quest is indeed from a different mod than the script I'm trying to modifiy, I'll just assume I need to use the getformfromfile option. Reading about on that it seems I need to start with: FormList weightmorphquest = Game.GetFormFromFile(0x01001883, "WeightMorphs.esp") as FormList Where 01001883 is the form id of the quest from WeightMorphs. That should get me the form id of the quest of interest stored in "weightmorphquest", right? Then looking at your other example I can access the function with: weightmorphquest.GetAliasByName(string WeightMorphsPlayerAlias) as WeightMorphs.ChangeWeight(0.25 * NoToDigest) *Not sure about the syntax, you seem to have a dangling parenthese somewhere* Am I at least on the right track with this?
Holzfrau Posted August 6, 2018 Posted August 6, 2018 4 minutes ago, Andy14 said: I deleted my post, it was nonsense, since you use a magecieffct. But to answer the question. Import would be like this: Import DigestScript If I understand correctly, NumberInStomach is a global one. Then you can access it in WeightMorphs too. I think you've got it backwards, he'd want to import WeightMorphs because he's trying to use it in DigestScript. But the problem with this, and the whole source of OP's question, is what reference would WeightMorphs be acting on? It needs to be attached to an actor, and you need a quest alias to make that connection. I am making an assumption here that the WeightMorphs script is written to affect whatever actor the reference is pointing to, otherwise implementing it as a ReferenceAlias extension wouldn't make any sense.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 17 minutes ago, Andy14 said: I deleted my post, it was nonsense, since you use a magecieffct. But to answer the question. Import would be like this: Import DigestScript If I understand correctly, NumberInStomach is a global one. Then you can access it in WeightMorphs too. No worries, most of this still feels like nonsense to me, combining classic programing with the need to redefine and specify elements from within the CK interface is taking me some time to get used to. You are correct that NumberInStomach is a global variable, so I could pull it within WeightMorphs. But then it seems I am stuck with a similar but inverted problem in that I would need to find a way to apply it within WeightMorphs only when the magiceffect (the digest power) from the other mod is applied.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 8 minutes ago, Holzfrau said: I think you've got it backwards, he'd want to import WeightMorphs because he's trying to use it in DigestScript. But the problem with this, and the whole source of OP's question, is what reference would WeightMorphs be acting on? It needs to be attached to an actor, and you need a quest alias to make that connection. I am making an assumption here that the WeightMorphs script is written to affect whatever actor the reference is pointing to, otherwise implementing it as a ReferenceAlias extension wouldn't make any sense. I think your assumption is correct (I won't pretend to even begin to understand how it all works) WeightMorphs uses the .tri files generated from Bodyslide to influence the shape of the player model on top of, and outside of what you can normally do with just the race menu.
Holzfrau Posted August 6, 2018 Posted August 6, 2018 5 minutes ago, Synake said: I was afraid something like that would be the case. Okay, so as you stated above, since the quest is indeed from a different mod than the script I'm trying to modifiy, I'll just assume I need to use the getformfromfile option. Reading about on that it seems I need to start with: FormList weightmorphquest = Game.GetFormFromFile(0x01001883, "WeightMorphs.esp") as FormList Where 01001883 is the form id of the quest from WeightMorphs. That should get me the form id of the quest of interest stored in "weightmorphquest", right? I see two problems here: That first byte is determined by load order. Change your form ID to 0x1883. You want it as a Quest, so do it as: Quest weightmorphquest = Game.GetFormFromFile(0x1883, "WeightMorphs.esp") as Quest 5 minutes ago, Synake said: Then looking at your other example I can access the function with: weightmorphquest.GetAliasByName(string WeightMorphsPlayerAlias) as WeightMorphs.ChangeWeight(0.25 * NoToDigest) *Not sure about the syntax, you seem to have a dangling parenthese somewhere* Am I at least on the right track with this? My parentheses weren't dangling, I had an extra set ? - the Papyrus compiler is a little finicky when you're throwing casts around. And don't forget you'll need to pass an actual string for the alias name, the compiler's going to puke on string WeightMorphsPlayerAlias.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 1 minute ago, Holzfrau said: I see two problems here: That first byte is determined by load order. Change your form ID to 0x1883. You want it as a Quest, so do it as: Quest weightmorphquest = Game.GetFormFromFile(0x1883, "WeightMorphs.esp") as Quest My parentheses weren't dangling, I had an extra set ? - the Papyrus compiler is a little finicky when you're throwing casts around. And don't forget you'll need to pass an actual string for the alias name, the compiler's going to puke on string WeightMorphsPlayerAlias. Thanks for all the help so far. So after making the changes to the GetFormFromFile part, am I defining a string variable then placing that into the function line?: string weightmorphalias = "WeightMorphsPlayerAlias" weightmorphquest.GetAliasByName(weightmorphalias) as WeightMorphs.ChangeWeight(0.25 * NoToDigest) or is that redundant and I just need to do something like: weightmorphquest.GetAliasByName("WeightMorphsPlayerAlias") as WeightMorphs.ChangeWeight(0.25 * NoToDigest)
Holzfrau Posted August 6, 2018 Posted August 6, 2018 2 minutes ago, Synake said: Thanks for all the help so far. So after making the changes to the GetFormFromFile part, am I defining a string variable then placing that into the function line?: string weightmorphalias = "WeightMorphsPlayerAlias" weightmorphquest.GetAliasByName(weightmorphalias) as WeightMorphs.ChangeWeight(0.25 * NoToDigest) or is that redundant and I just need to do something like: weightmorphquest.GetAliasByName("WeightMorphsPlayerAlias") as WeightMorphs.ChangeWeight(0.25 * NoToDigest) You can inline it like your last snippet. I think you'll still need that extra set of parentheses like I had in my original example. Let me know if it works out!
Macross. Posted August 6, 2018 Author Posted August 6, 2018 3 minutes ago, Holzfrau said: You can inline it like your last snippet. I think you'll still need that extra set of parentheses like I had in my original example. Let me know if it works out! Hmm, it doesn't seem to like something about the getform line, its throwing the following at me: S:\Programs\Steam\steamapps\common\Skyrim\Data\Scripts\Source\DigestScript.psc(11,29): no viable alternative at input 'Game' S:\Programs\Steam\steamapps\common\Skyrim\Data\Scripts\Source\DigestScript.psc(11,29): required (...)+ loop did not match anything at input '.' S:\Programs\Steam\steamapps\common\Skyrim\Data\Scripts\Source\DigestScript.psc(11,6): Unknown user flag Game I'm checking for the errors now.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 Scratch that, I didn't know that line also needed to be inside the event call. Fixed, and compiled fine now. Will hop into Skyrim to see if it works as intended.
Macross. Posted August 6, 2018 Author Posted August 6, 2018 28 minutes ago, Holzfrau said: You can inline it like your last snippet. I think you'll still need that extra set of parentheses like I had in my original example. Let me know if it works out! Worked beautifully! Thank you so much for the help and your patience! ?
GenioMaestro Posted August 6, 2018 Posted August 6, 2018 Well ... you're fighting a common problem for older programmers, like me, when you work with CK. As you know, in a papyrus script, you can create a Property of any Type of all Types that has the CK: Spoiler GlobalVariable Property GameDaysPassed Auto Actor Property PlayerRef Auto MagicEffect Property VampireSightEffect Auto Quest Property MQ101 Auto FormList Property Eyes_Female Auto TextureSet Property CX_Female_Elf Auto Race Property ElfRaces Auto But one of the most strange points is that you can create a property of type SCRIPT and link it with CK But the property TYPE that you must use is the name of the script. Look the diference: SPELL Property Queen Auto WeightMorphs Property WMS Auto In the first line you are creating a property of type SPELL called Queen. In the second line you are creating a property of type WeightMorphs called WMS(WeightMorphsScript) This two properties MUST BE FILLED in CK for work. For correctly FILL this SCRIPT type Property, first you must COMPILE your script and second you must LINK the property in CK making this: Spoiler In this way you get a Property that aim to another script and link it with the pure internal object of the game. For the game all are object of diferent type, Spell, Global, Script, but Spell, Global are fixed types and Script is a dinamic class for dinamically create diferent objects using the NAME of the script. It's a bit strange for OLD programmers, but that's the way it is. Your final script must look as: Spoiler Scriptname DigestScript extends activemagiceffect WeightMorphs Property WMS Auto Event OnEffectStart(Actor akTarget, Actor akCaster) float NoToDigest = NumberInStomach.GetValue() WMS.ChangeWeight(0.25 * NoToDigest) EndEvent In this way you are creating a HARD dependency from the other mod, because your are ussing her script that is inserted in her ReferenceAlias that depend from her Quest, and when publish your mod you must say that your have the REQUERIMENT of install the dependant mod. For make a SOFT dependency you must use the way said by Holzfrau and follow her indications. The result is the same in execution because you are making exactly the same, and the only diference is the HARD or SOFT dependencie/requeriment of the other mod. When you write this line: Quest weightmorphquest = Game.GetFormFromFile(0x1883, "WeightMorphs.esp") as Quest you are getting, in dinamic way(execution time) a link to the ESP file of the other mod. This is made by CK in HARD way when you fill the property and CK store the HARD link in your esp. As you linked with the quest, because is the only way for link with another esp in the next line: weightmorphquest.GetAliasByName(string WeightMorphsPlayerAlias) as WeightMorphs.ChangeWeight(0.25 * NoToDigest) you must make some obligatory cast for obtain the correct type of variable(or object) need for make correct call to the function.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.