Editting Papyrus Base Scripts - Actor.psc, ObjectReference.p

Post » Wed Jun 20, 2012 9:15 am

It appears to me that modders should not leave the power of editing base scripts untapped when needed. Naturally, the great caveat with this is that no two such edits will presently be compatible. I ask primarily what we can do about this.

I wonder
  • Is the premise wrong? That is, to contradict it, is there virtually always an alternative to modifying base scripts such as Actor.psc, ObjectReference.psc, etc.?
  • If not, what system could we device to render base-script edits compatible?
  • What mods do you know which presently edit base scripts?
Longer story
Spoiler

Synopsis in place, I have to admit - I have never before written a mod for TES; I may be greatly mistaken in this topic and if so, I apologize for jumping to conclusions.

My own motivation for this post was a dialogue-driven disposition system for Skyrim with multiple variables (affection, respect etc.). To this end, I aimed to add to every NPC a number of ActorValues accessible through in particular dialogues. Memory concerns besides the topic, I researched thoroughly for a way to achieve this and eventually gave up in lieu of modifying Actor.psc directly. This worked splendidly but I could find no apparent way to do so while maintaining compatibility with other scripts taking the same approach, unless we coordinate a system. Unfortunately you cannot `alias' a class. How would you do this?

For completeness sake, the (efficient) approaches I've so far seen in scripts modifying objects universally, e.g., all NPC's, guards, books, or the like, exploit one of the following four methods. Please correct me if you've seen more.
  • Quests processing: possibly through aliases, one can run a script repeatedly on a set of objects, but as far as I'm aware, it does not offer efficient and persistent object-specific variables.
  • Active (magic) effects: attaches to an actor and permits adding new variables as well as to process actor events. However, I know of no (simple) way to make newly-added properties accessible in universal dialogues. (Granted, one could force an event on the magic effect which causes it to store its variables in global properties, modify the same, and cause a new event to store them back.) Might also be feasible if SKSE were to provide additional enumeration methods.
  • ScriptDragon: also runs continuously and permits new variables. With e.g. hashes, also object-specific ones. However, I can not figure out how to hook such variables up to e.g. dialogues.
  • Attach an actor script to every X: does not work with X's added by new mods, causes incompatibilities, and involves a ton of work.
These approaches will likely suffice for most scripts and should not be complicated further. However, they all possess limitations, some of which may be alleviated by modifying base scripts. It is power which one should be keen to give up in vain.

For those who wonder what I mean by modifying `base scripts': if you download the Creation Kit, you will find Actor, ObjectReference, Book, and other base Papyrus classes in the Creation Kit (Gameplay>Papyrus Script Manager), as well as text files in the /scripts/source directory which may be compiled to pex files with the papyrus compiler. Modifying these scripts indeed affect all in-game objects instantiating these classes or extending classes thereof.

Enough blabbering. It seems to me that there is sometimes no other viable option but to modify base scripts. Am I wrong and if not, how can we do this while maintaining script compatibility?

Thanks for reading.

http://forums.nexusmods.com/index.php?/topic/632637-editting-papyrus-base-scripts-actorpsc-objectreferencepsc-etc
User avatar
Mandy Muir
 
Posts: 3307
Joined: Wed Jan 24, 2007 4:38 pm

Post » Wed Jun 20, 2012 8:49 pm

If you are considering adding scripts to every actor, you can consider using http://www.uesp.net/wiki/Tes5Mod:SkyProc to very simply do that. I already engage that for attaching a unique increased spawns script to every NPC, along with other things like automatic spells.

It could be possible to process scripts along the same vein, if there were interest in creating a program for it. I think the SKSE team was looking at a few ways of implementing that, as they'll have to deal with those factors when releasing new papyrus functions.
User avatar
Phillip Hamilton
 
Posts: 3457
Joined: Wed Oct 10, 2007 3:07 pm

Post » Wed Jun 20, 2012 8:04 pm

If you are considering adding scripts to every actor, you can consider using http://www.uesp.net/wiki/Tes5Mod:SkyProc to very simply do that. I already engage that for attaching a unique increased spawns script to every NPC, along with other things like automatic spells.

It could be possible to process scripts along the same vein, if there were interest in creating a program for it. I think the SKSE team was looking at a few ways of implementing that, as they'll have to deal with those factors when releasing new papyrus functions.

I'm not sure whether SkyProc is always the best way to add scripts to all actors, mostly because if I understand it correctly, using it would loop through all actors in a .esm or .esp file and add the scripts to them, just to save on the time it would require to do so manually. However, this still doesn't fix the other problems that occur when directly adding scripts to all actors, which are that the mod becomes incompatible with any mod changing any one of those actors, and that new actors from other mods will remain unaffected (generally when you're dealing with a mod which adds scripts to all actors, you'll really want ALL actors, not just vanilla actors).

To achieve this you can either use a continuously restarting quest with a number of quest aliases with scripts (and every time the quest restarts, you fill the quest aliases with all actors near you) or you use a quest script which is constantly updating and has one or more FindRandomActorFromRef(player, 2000) calls and adds a scripted magic effect to each actor it finds.
User avatar
JR Cash
 
Posts: 3441
Joined: Tue Oct 02, 2007 12:59 pm

Post » Wed Jun 20, 2012 8:08 pm

Like all other assets in the game, the last-loaded script will override all other versions of a script. So if you make changes to the same script that another mod makes changes to, the last-loaded mod wins. Also, these “native” scripts are not attached to everything in the game. They are only attached when and if necessary. If an actor in game is never referred to in script, he will never have an actor script attached to him.

I would not recommend adding any data to the “native” scripts because if you have two scripts attached to the same in-game object that derive from the same script with data on it, you have two copies of that data attached. So if you, say, add a new “actor value” to Actor.psc, there will actually be X independent copies of the “actor value” attached to that actor, where X is 0 if no one uses the actor in script, and X is N or N+1 where N is the number of scripts attached to the actor (some rare instances may cause Actor.psc to be attached by the game to the actor in addition to any other scripts already on the actor, hence the +1)

If your variable or property pointing at your actor is just the base actor type it will be relatively random which actor-derived script you are going to actually be pointing at, and therefore, which copy of the “actor value” you will be examining and modifying, though you can convert the variable to a string if you need to debug such a situation (which will tell you exactly which script you are pointing at).
User avatar
Dalley hussain
 
Posts: 3480
Joined: Sun Jun 18, 2006 2:45 am

Post » Wed Jun 20, 2012 9:48 pm

Interesting. I was really curious to why not all the actors use actor script. Thanks for the info :)
User avatar
MISS KEEP UR
 
Posts: 3384
Joined: Sat Aug 26, 2006 6:26 am

Post » Wed Jun 20, 2012 8:49 am

If you are considering adding scripts to every actor, you can consider using http://www.uesp.net/wiki/Tes5Mod:SkyProc to very simply do that. I already engage that for attaching a unique increased spawns script to every NPC, along with other things like automatic spells.

It could be possible to process scripts along the same vein, if there were interest in creating a program for it. I think the SKSE team was looking at a few ways of implementing that, as they'll have to deal with those factors when releasing new papyrus functions.
I'm not sure whether SkyProc is always the best way to add scripts to all actors, mostly because if I understand it correctly, using it would loop through all actors in a .esm or .esp file and add the scripts to them, just to save on the time it would require to do so manually. However, this still doesn't fix the other problems that occur when directly adding scripts to all actors, which are that the mod becomes incompatible with any mod changing any one of those actors, and that new actors from other mods will remain unaffected (generally when you're dealing with a mod which adds scripts to all actors, you'll really want ALL actors, not just vanilla actors).

To achieve this you can either use a continuously restarting quest with a number of quest aliases with scripts (and every time the quest restarts, you fill the quest aliases with all actors near you) or you use a quest script which is constantly updating and has one or more FindRandomActorFromRef(player, 2000) calls and adds a scripted magic effect to each actor it finds.
SkyProc is indeed a universal method that I had missed. I would have to agree with Borgut1337 that it sadly appears to offer limited compatability but it's an interesting option for processing mods. Will keep it mind, thanks!

Borgut1337 - How would you store object-specific variables through quest processing? E.g. suppose you wanted to keep track for every NPC the number of times it has been hit.
User avatar
Stacey Mason
 
Posts: 3350
Joined: Wed Nov 08, 2006 6:18 am

Post » Wed Jun 20, 2012 2:44 pm

Like all other assets in the game, the last-loaded script will override all other versions of a script. So if you make changes to the same script that another mod makes changes to, the last-loaded mod wins. Also, these “native” scripts are not attached to everything in the game. They are only attached when and if necessary. If an actor in game is never referred to in script, he will never have an actor script attached to him. I would not recommend adding any data to the “native” scripts because if you have two scripts attached to the same in-game object that derive from the same script with data on it, you have two copies of that data attached. So if you, say, add a new “actor value” to Actor.psc, there will actually be X independent copies of the “actor value” attached to that actor, where X is 0 if no one uses the actor in script, and X is N or N+1 where N is the number of scripts attached to the actor (some rare instances may cause Actor.psc to be attached by the game to the actor in addition to any other scripts already on the actor, hence the +1) If your variable or property pointing at your actor is just the base actor type it will be relatively random which actor-derived script you are going to actually be pointing at, and therefore, which copy of the “actor value” you will be examining and modifying, though you can convert the variable to a string if you need to debug such a situation (which will tell you exactly which script you are pointing at).

This is highly relevant input and rules out my initial ideas. Great many thanks, SmkViper! Are details like these documented somewhere? In particular, is there any way to attach a new script through scripts, e.g. akin to AttachPapyrusScript?

I suppose a system for editting base scripts in that case works better through delegation to new scripts/classes, passing functions for potential overriding with the Actor as argument, and permitting access to object-specific variables in e.g. dialogues only if one has a hard-coded reference such as `ActorMod003'. Not most beautiful but works with the present information.

Kudos!
User avatar
Nomee
 
Posts: 3382
Joined: Thu May 24, 2007 5:18 pm

Post » Wed Jun 20, 2012 9:12 pm

SkyProc is indeed a universal method that I had missed. I would have to agree with Borgut1337 that it sadly appears to offer limited compatability but it's an interesting option for processing mods. Will keep it mind, thanks!

Borgut1337 - How would you store object-specific variables through quest processing? E.g. suppose you wanted to keep track for every NPC the number of times it has been hit.

I guess you could create a token (a useless piece of armor set to unplayable so the player doesn't see it) and add one to the NPC's inventory every time he's hit. That way the tokens will remain there even if the scripts disappear again because the player isn't nearby anymore (in the case of quest aliases) or because the NPC has died (in the case of magic effects)
User avatar
Dominic Vaughan
 
Posts: 3531
Joined: Mon May 14, 2007 1:47 pm


Return to V - Skyrim