Jump to content

[LE] Getting my custom follower to use Serana-style sandboxing


Dahveed

Recommended Posts

I recently made a custom-framework follower using Joseph Russel's youtube tutorial (

4 parts total) and the basics are coming along nicely.

 

However I have a couple of problems I can't figure out.

 

One, as the title suggests, is that I can't seem to get my follower to "sandbox" while my player is idle while she is following me, as other follower NPCs seem to be able to do.

 

I've made a copy of serana's sandbox package DLC1NPCSandboxAroundPlayer600 and I basically remove all the Serana-specific conditions. I have 4 total conditions, "waitingforplayer=0", "isplayermovingintonewspace=0", "issneaking=0", and "getdistance<600".

 

I've tried setting the "Owner Quest" to my follower quest, but leaving this to none doesn't seem to affect anything.

 

I haven't changed much, and I have indeed added that package list to my NPC in the actor window (under AI packages).

 

But it won't trigger :/

 

 

 

Also, the second problem I have is that she won't notice any corpses. I just added about 10 different random things that might play, but none of them EVER trigger. I have very minimal conditions, and I even reverse-engineered other follower mods that do this (Anna NPCs) and all my conditions etc. seem to be identical. It's like there's some invisible thing overriding everything in the default follower package.

 

 

Any ideas about what I haven't checked for would be greatly appreciated!

Link to comment
Share on other sites

What is the exact package stack of the follower right now, and can you list all their conditions?

 

But I'm not sure if a Serana AI can be done with just packages and their conditions though. You'll probably need a script that monitors when the player stopped, and then after a few seconds, changes the package to the sandboxing one (and back to the follow package once the player is moving again). You can either check the original Serana AI script for this example, or if you're still stuck, let me know and I'll post the code here with explanations.

 

 

I don't know about the corpse noticing, someone else will have to help with that.

Edited by WhiteWolf424242
Link to comment
Share on other sites

What is the exact package stack of the follower right now, and can you list all their conditions?

 

But I'm not sure if a Serana AI can be done with just packages and their conditions though. You'll probably need a script that monitors when the player stopped, and then after a few seconds, changes the package to the sandboxing one (and back to the follow package once the player is moving again). You can either check the original Serana AI script for this example, or if you're still stuck, let me know and I'll post the code here with explanations.

 

 

I don't know about the corpse noticing, someone else will have to help with that.

With the "corpse noticing" that seems to be Vanilla follower behavior, I just took Lydia for a spin and she didn't notice corpses until I dismissed her either. I'm not sure what kind of magic trick Anduniel did to get her follower to behave differently, I messaged her and she told me she just "added a currentfollower condition", which didn't work for me. /shrug

 

I haven't the slightest skill at scripting, I already tried looking at the Serana scripts and I don't have a clue.

 

As far as my follower's "package stack", as far as I know I don't even have any packages. I just have the follower quest set up as per Joseph Russel's instructions, so she has basic recruitment dialogue and such.

Link to comment
Share on other sites

All right. I imagine that this will look daunting then, but I'll try to walk you through it.

 

The entire code:

 

 

Scriptname SeranaAIScript extends Quest  Conditional

int Property UpdateInterval auto
float Property SettleRadius auto
int __historySize = 8
float[] __playerPosX
float[] __playerPosY
float[] __playerPosZ
bool Property PlayerSettled Auto Conditional
ReferenceAlias Property AstridFollowerAlias  Auto


function Setup()
    ; history of player position over the last __historySize updates
    __playerPosX = new float[8]
    __playerPosY = new float[8]
    __playerPosZ = new float[8]

    Actor _player = Game.GetPlayer()
    int count = 0
    while (count < __historySize)
        __playerPosX[count] = _player.X + 1000
        __playerPosY[count] = _player.Y + 1000
        __playerPosZ[count] = _player.Z + 1000
        count += 1
    endwhile

    RegisterForUpdate(UpdateInterval)
EndFunction
        
function Shutdown()
    UnregisterForUpdate()
endfunction
        
event OnUpdate()
    int historyIndex = 0
    while (historyIndex < __historySize - 1)
        __playerPosX[historyIndex] = __playerPosX[historyIndex + 1]
        __playerPosY[historyIndex] = __playerPosY[historyIndex + 1]
        __playerPosZ[historyIndex] = __playerPosZ[historyIndex + 1]

        historyIndex += 1
    endwhile

    Actor _player = Game.GetPlayer()
    __playerPosX[__historySize - 1] = _player.X
    __playerPosY[__historySize - 1] = _player.Y
    __playerPosZ[__historySize - 1] = _player.Z

    
    bool switchedPackageConditions = False

    float xFactor = (__playerPosX[0] - _player.X)
    xFactor = xFactor * xFactor
    float yFactor = (__playerPosY[0] - _player.Y)
    yFactor = yFactor * yFactor
    float zFactor = (__playerPosZ[0] - _player.Z)
    zFactor = zFactor * zFactor

    float distance = Math.sqrt(xFactor + yFactor + zFactor)

    ; if the player has moved less than the defined settle radius,
    ;   set the flag that the sandbox package is looking for.
    if (distance > SettleRadius)
        if (PlayerSettled == true)
            switchedPackageConditions = true
        endif
        PlayerSettled = false
    else
        if (PlayerSettled == false)
            switchedPackageConditions = true
        endif
        PlayerSettled = true
    endif

    if (switchedPackageConditions)
        if (AstridFollowerAlias.GetReference())
            Actor Follower = AstridFollowerAlias.GetActorReference()
            if (Follower.GetActorValue("WaitingForPlayer") == 0)
                Follower.EvaluatePackage()
            endif
        endif
    endif
EndEvent

 

 

This script should be attached to a Quest, preferably to the one where you handle the dialogue of your follower.

Set the UpdateInterval property to 1, and the SettleRadius property to the radius in which the player must remain in for the sandboxing to happen. 150-ish should be okay.

Set the PlayerSettled property to false.

Set the AstridFollowerAlias property to a Quest Alias that contains your follower as Unique Actor, at all times. (I did not rename the variables, and you don't have to either, but you can if don't want the variable to be called 'Astrid...'. If you do rename it, make sure to rename it everywhere in the code, use a replace feature, don't edit by hand.)

 

 

What the script does, is that it monitors player movement. If the player has stopped within a set radius, then it changes a Quest Variable for the packages, and forces the Follower to evaluate its stack. Once the player starts to move again, it does the same.

 

Because this is a constantly running monitoring script, we don't want it to eat performance while the follower is not even following you.

When your follower is recruited with the "FOllow me" dialogue, you can use

(GetOwningQuest() as SeranaAIScript).Setup()

In the topic fragment to start monitoring.

 

Similarly, in the dismiss dialogue, you'll have to put

(GetOwningQuest() as SeranaAIScript).Shutdown()

to stop the script.

 

Now you'll need to setup the Packages. You need to add this condition to the FollowPlayer-type package:

GetVMQuestVariable[ YourQuestThatTheScriptIsAttachedTo:: PlayerSettled ] == 0

 

And for the sandboxing package, you'll need this condition:

GetVMQuestVariable[ YourQuestThatTheScriptIsAttachedTo:: PlayerSettled ] == 1

 

Now make sure to add these packages to the alias that contains your follower in the quest. If you added the condition to both, then the order shouldn't matter.

We add packages to quest aliases instead of directly to the NPC is because quest alias packages are added to the top of their stacks, and are evaluated based on quest priority.

Make sure to set your quest priority rather low, so that if anything more important than sandboxing is trying to push something to the stack, it can (but since this is a standalone follower, this won't be an issue. It's still good practice to follow).

 

And there you have it. Your follower should now sandbox just like Serana.

Let me know if it works or if you need more help with it :)

Edited by WhiteWolf424242
Link to comment
Share on other sites

Coincidentally someone JUST uploaded a mod that does exactly this... Without ANY scripting! :ohmy:

 

I really appreciate your effort to help me but I just integrated his package into my mod and it works! It probably won't have the same functionality or "intelligence" as Serana's, but it does what I need it to do.

 

I might have a look anyways to see if I can maybe learn something, but either way, thanks very much for your help!

Link to comment
Share on other sites

  • Recently Browsing   0 members

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