Jump to content

[Modding] Two questions regarding objects and Aliases


Recommended Posts

Heyho,

 

My first question is: how can I spread an item across Skyrim as loot, without altering LeveledItem lists in the CK? I don't want my users to rely on some Bashed Patches or something.

In practice I want to put a little wearable (eg a ring or an amulet) into chests and/or dead bodies. The chance for it to appear should be choosable by the user.

Basically I want to copy the Lucky Charm of DCUR for my mod Mimic Clothes, but I wasn't able to figure out how DCUR spreads keys and the Charm ?

 

My second question: I want to tie followers into my mod eventually. So I created a ReferenceAlias, that gets filled by condition: close to PlayerRef and in CurrentFollowerFaction.

Now my question: If there are multiple followers, will this alias get overwritten whenever a new follower gets closer to the player than the other follower was, who filled the alias before? Or is it fixed as soon as the first follower filled the alias?

 

Here's how I want to fill the alias

Spoiler

image.png.1da64387e6913b1a1e76db97f6768326.png

 

Question 2.5) I want to expand the script that listens to events to trigger mimics. So a new script for followers, that extends the event script of the player and gets attached to the follower alias, just to cut out the snippets that only should run for the Player. The rest should run off the base script. Here some example code snippets:

 

Spoiler

Base script:

Scriptname dmcTriggerEvents extends ReferenceAlias
{The main events by this mod to trigger a mimic}

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
	; other code
	MainTrigger.TriggerMimic(mlibs.libs.PlayerRef, akMimic, mcm.fEquipBaseChance)
	; other code
EndEvent

;/
	other events
;/

 

 

Now I want to use this for followers:

Scriptname dmcFollowerEvents extends dmcTriggerEvents
{The main events by this mod to trigger a mimic}

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
	; reduced code
	MainTrigger.TriggerMimic(Parent as Actor, akMimic, mcm.fEquipBaseChance)
	; reduced code
EndEvent

;/
	other events
;/

 

 

 

Currently it uses a fix property, filled with the Player as actor to decide who's the victim. I already tried the keywords "Self" or "Parent" but those give the error that ReferenceAlias can't cast to Actor as those are incompatible. How can I get inside the script event, which alias received the event?

Edited by Mister X
Link to comment
1 hour ago, Mister X said:

In practice I want to put a little wearable (eg a ring or an amulet) into chests and/or dead bodies. The chance for it to appear should be choosable by the user.

Basically I want to copy the Lucky Charm of DCUR for my mod Mimic Clothes, but I wasn't able to figure out how DCUR spreads keys and the Charm ?

 

Going by the fact that DCUR doesnt work on modded containers, I strongly assume it uses the strategy shown in this beginner tutorial on the CK wit hthe "dynamically attaching scripts to objects"

 

another way to achieve this is through the way I did it in TT:

Function maintenance()
  RegisterForMenu("ContainerMenu")
EndFunction

Event OnMenuOpen(string Menu)
  ObjectReference[] boxz = MiscUtil.ScanCellObjects(28, PlayerRef, 400.0)
  int index = 0
  While(index < boxz.Length)
    int openstate = boxz[index].GetOpenState()
    If(openstate == 1)
      prepareEncounter(boxz[index])
      return
    EndIf
    index += 1
  EndWhile
EndEvent

 

What this does is essentially every time the Player opens a Chest, you look for an OpenChest (openstate == 1) by scanning for every container close to the player (boxz)

By logic, in almost all instances the only chest which should be open near the player while the player is looting a chest should be the chest the player is currently looting (yes, actually). With this, you have access to the very chest the player just opened and can add w/e Item you want (or do other fancy stuff like I do in TT)

 

The 400 is roughly the range the player can interact with objects. Any higher means that you will look for objects that the player cant interact with anyway (= unnecessary checks which lower performance) and any lower might skip the chest the player just opened because the player opened the chest at their max possible range. So if you use this method, stick with the 400

 

This method is also a lot lighter and more reliable than what the CK Tutorial tells you as its only active when actually opening a chest and works with any and every container, including modded ones

 

1 hour ago, Mister X said:

Now my question: If there are multiple followers, will this alias get overwritten whenever a new follower gets closer to the player than the other follower was, who filled the alias before? Or is it fixed as soon as the first follower filled the alias?

The game only filles an alias once: When the Quest starts. If you want to replace the Alias with something else you need to do so through a Script using "Alias.ForceRefTo(ObjRef)"

If you want to start the Quest before the Player might not have a Follower, you need to set the Follower Alias to optional and use some sort of Scan or manual trigger to add the Follower to the Frame. You can look into Subm. Lola, Devious Fol. or Joyful Fol. to see how theyre doing this

 

Near Alias doesnt work the way you want it there btw, thats only used in combination with Linked Refs

 

1 hour ago, Mister X said:

Question 2.5) I want to expand the script that listens to events to trigger mimics. So a new script for followers, that extends the event script of the player and gets attached to the follower alias, just to cut out the snippets that only should run for the Player. The rest should run off the base script. Here some example code snippets:

If majority of your script shouldnt trigger on Followers, do a new Script for Followers

 

The "parent" Alias references the scripts parent, the thing that this script is extending. Compare it to the "super" keyword in java, thats only useful if you have a custom (child) Script that extends another custom (parent) Script  with the child script containing the same method as the parent script. Normally, the child script would overwrite the parents implementation of the method but in certain instanes you might want to not use the childs implementation, so to avoid having to rewrite your script somehow you just use the "parent" keyword to call the parents implementation of the script, ignoring the childs one

 

The "self" variable is equal to the "this" keyword in java and only points at your own Object. In this case, "Self" points at the current instance "dmcTriggerEvents" which extends ReferenceAlias and is attached to the ReferenceAlias Object in the Alias Tab of your Quest, meaning it contains all Methods & Properties in both the dmcTriggerEvenst & ReferenceAlias Script and the very ReferenceAlias Object it is attached to in the CK. To simplify it, a little example:

Spoiler

You got an Item "itm" which is stored in the Players Inventory and you want to move it into the Inventory of "theOtherActor". Now, how do you do that?

2 simple ways:

 

1) attach a Script on the Player:

RemoveItem(itm, akOtherContainer = theOtherActor)

This would be the most straightforward thing, here you call RemoveItem on the Player which well.. removes the itm from the Player Inventory and moves it into theOtherActor's one, now unfortunately you dont want to edit the Player, so instead it might be smart to attach the script to theOtherActor instead:

 

2) attach a script on theOtherActor

Game.GetPlayer().RemoveItem(itm, akOtherContainer = Self)

What we do here now, is telling the Script it should take the Player, look into their Inventory and remove the Item "itm" from it and then move this item into the reference this script is attached to

Since the Script youre calling this from is attached to theOtherActor, Self would here point at theOtherActor and move this item into that actors inventory

 

Due to how abstract papyrus is, understanding and utilizing Self & Parent can be a bit tricky, especially the Parent one. Properly extending Scripts in Papyrus is rather unreliable so you wont see this Keyword being used too often. Self is a Keyword that is usually forgotten but but used a whole lot internally. When you call "GetReference()" in a ReferenceAlias Script you actually call "Self.GetReference()" because what you want is the Reference of the Object this current Script is attached to you can do this pretty much everywhere. Everytime you call a Method or Property (not local variable) without referencing from where that Property or Method is from, youre essentially skipping a "Self" keyword

Edited by Scrab
Link to comment

For 1)

Thanks, that's really helpful, may I utilize that snippet?

 

For 2)

Ok, I'll take a look at one of the mods when I have time. Until then, am I right, when I assume that roughly spoken it's the easiest way to create an EMPTY alias, set to optional, and then run some periodic code that checks for followers and fills the alias(es) once it finds one, based on my needed filters?

 

For 2.5)

That is exactly what I want: Basically the same events should run the same code for both player and follower. So I wanted to extend the player script like above and attach that follower script to the follower alias. Like that, when the follower equips an armor, it should run the event of the player event script, right?

Now, as the actual code only is present in the player event script, how can I get WHO had the event? Does Self.GetReference() do the trick or will that always be the player, when the script is attached to the player RefAlias?

Link to comment
23 minutes ago, Mister X said:

may I utilize that snippet?

sure

 

23 minutes ago, Mister X said:

then run some periodic code that checks for followers and fills the alias(es) once it finds one, based on my needed filters?

yes

 

23 minutes ago, Mister X said:

So I wanted to extend the player script like above and attach that follower script to the follower alias. Like that, when the follower equips an armor, it should run the event of the player event script, right?

Theoretically yes but on a personal recommendation: dont do it

 

I tried doing something like that multiple times already and it never worked perfectly fine and reliable the way I wanted it to. Youre better of having one "main script" which stores all this shared utility and make 2 scripts which both just call functions from that main script

 

Edited by Scrab
Link to comment
25 minutes ago, Scrab said:

Youre better of having one "main script" which stores all this shared utility and make 2 scripts which both just call functions from that main script

 

I already have a script MainTrigger, attached directly to the base quest, which has the main function to do the nasty stuff. This one main function gets called from another script:

TriggerEvents is attached to the RefAlias that's filled with the player and has only the events that all do call the same function in the MainTrigger file.

 

I now only want to utilize those same events for the followers, too. To have less work, I wanted to use the already written code for the events. So, it would be easier to make a new script, which purely holds the events for the followers, and that basically has the same code again?

Link to comment
41 minutes ago, Mister X said:

So, it would be easier to make a new script, which purely holds the events for the followers, and that basically has the same code again?

Its a recommendation. Ive had nothing but bad experiences trying to extend another script and utilizing both at the same time

 

Its certainly easier to just extend another script instead of copypaste everything and in any other language youd be stupid not doing it but in Papyrus I dont recommend it because reliability. Things just randomly dont work because extended script interact in a really weird way with each other 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use