Creation Kit – Rude Followers

Sometimes NPCs are jerks. They will see you clearly engaged in a conversation with another person, and yet still find the need to rudely babble in the background about the layout of the city or the rich history of their underpants. It would be nice if there were a way to prevent this, and there technically is. It’s just a ton of work.

The problem is there is no single condition that stops the quest when appropriate – it has to be applied to individual NPCs and scenes. At least, as far as I know. I could be wrong. Please let me be wrong.

The video above demonstrates how this brute force tactic works. A condition has been placed on the DialogueFollower3DNPC quest to not run while MorthalInitialScene is playing. A similar condition IsInDialogueWithPlayer can be run on individually referenced NPCs, such as Al’Hassan in the picture below.

notalkiewhentalking

The reason I’ve been slow in implementing these conditions is because I’m not entirely sure this is the only way to go about it. It certainly isn’t the most efficient. So it’s a low priority, because eventually someone smart is going to make all of this brutality a complete waste of time. It’s possible someone already has.

EDIT: It appears that the scenes are considered “playing” if you’ve never seen them. Meaning, the IsScenePlaying condition has to be applied to individual comments instead of an entire quest. So it’s useless.

31 thoughts on “Creation Kit – Rude Followers

  1. yeah, i need a non-skse that works regardless of who starts the conversation. many of the important dialogues are forcegreets. it also has to work for scenes.

    i suppose if there isn’t a way the brute force doesn’t take all that long. i did morthal today in like 5 minutes. but feel free to post your method here if you’d like, as i’m curious to know what it is.

    1. Forget what I said before, see if this works:

      ——————————————————————————————————————————-

      Actor Function GetPlayerDialogueTarget(INT iLoopIterations = 15, Float fAreaToSearch = 350.0)

      Actor Player = Game.GetPlayer()
      Actor Target

      While iLoopIterations > 0
      Target = Game.FindRandomActorFromRef(Player, fAreaToSearch)
      iLoopIterations -= 1
      If Target && Target != Player && Target.IsInDialogueWithPlayer()
      iLoopIterations = 0
      Else
      Target = NONE
      EndIf
      EndWhile

      Return Target
      EndFunction

      ——————————————————————————————————————————-

      The parameters are optional, but you might want to adjust them depending on the situation, they should handle any normal situations though. But if you make them different, keep proportional.

      -The first one is how many times the script will run trying to find the actor talking to the player
      -The second is how large will be the radius of search (around the player)

  2. okay, i get what the script does – checks 15x to find a person within 350 units, makes sure it’s not the PC and is in dialogue with PC – and you could easily put a stage or globalvariable(depending on whether a target was found) that the follower quest could check for. But as i am a noob, how would i implement it?

    I am new to scripting so you’d have to walk me through it.

    Edit: Also, how resource intensive is it to have this script always running? And any way to work in scenes?

  3. If I understand well what you need to check, the condition should only be needed in the dialogue of the follower. As for running the script from a condition check, I think we could pull off something using the GetVMQuestVariable() condition. I wouldn’t recommend globals though, as they get stuck in the savefile.

    As for how script-intensive it would be, I wouldn’t recommend running it more than one time each four-five seconds. But the best way to know is to run it and test the papyrus performance.

    Try this:

    -Attach this script to a quest (any quest, really):

    ————————————————————————————————————
    ScriptName BARBASDialogueDetection_SCRIPT Extends Quest Conditional

    Actor Property PlayerDialogueTarget Auto Conditional

    Event OnInit()

    RegisterForSingleUpdate(1.0)
    EndEvent

    Event OnUpdate()

    PlayerDialogueTarget = GetPlayerDialogueTarget()
    RegisterForSingleUpdate(4.0)
    EndEvent

    Actor Function GetPlayerDialogueTarget(INT iLoopIterations = 15, Float fAreaToSearch = 350.0)

    Actor Player = Game.GetPlayer()
    Actor Target

    While iLoopIterations > 0
    Target = Game.FindRandomActorFromRef(Player, fAreaToSearch)
    iLoopIterations -= 1
    If Target && Target != Player && Target.IsInDialogueWithPlayer()
    iLoopIterations = 0
    Else
    Target = NONE
    EndIf
    EndWhile

    Return Target
    EndFunction
    ————————————————————————————————————

    -If you just want to check whether the player is in conversation or not, the condition must be: GetVMQuestVariable [THIS SCRIPT] PlayerDialogueTarget != 0

    -However, if you want to know WHO is talking to the player, you can still import the script and get the property

    Let me know :)

  4. okay, i made the quest with the script. then i go to dialoguefollower3DNPC, and add a condition to the quest dialogue condition window? There’s a GetVMQuestVariable condition, but for value I can only select “none.” I guess I need to know how to add the variable to the detection quest. Sorry, I am dumb.

    As for pros and cons, I take it the pros would be this script would save me time. Cons would be running a script every 4 seconds, it doesn’t work on scenes, and it wouldn’t apply if the idle commentary fired in the 4 second gap. Also, if someone wished to uninstall, would this run in perpetuity unless the quest was stopped?

    As for pros and cons for brute force, does adding a bunch of conditions effect performance? If not, pros would be it’d work without the use of scripts as well as scenes, cons would be it’d take a while to implement and can’t be done on non-persistent NPCs(as turning them persistent I assume would be a drain on performance).

    In any case, thanks for the help. It is much appreciated.

  5. Sorry, it took me a little while to get the CK running on this bloody new Microsoft system. About the condition only showing NONE, it was my fault :P . Change the PlayerDialogueTarget property type from Actor to BOOL and all should go smoothly.

    -About pros and cons: a little 15-iteration script running every 4 seconds wouldn’t hurt most systems much, but if you’re worried about it, you could add another condition to check if the follower is close enough to the player; so it would only run the script if the follower is – let’s say – < 200 units close to the player.

    -No, it wouldn't work on scenes, but the worst that could happen about the 4s gap is that for the first 4 seconds of the conversation wouldn't be registered by the script, and therefore, the companion may (still a small possibility) say something during these first seconds.

    -On uninstalling, if I'm not mistaken in my reasoning, because of my use of RegisterForSingleUpdate(), the first time the game loads and the script isn't there any longer, it will automatically end, as the code which would register the next iteration is no longer there. This also prevents save bloat due to low script performance (update stacking).

    -Yes, making them persistent would mean a huge load of additional work on the CPU (as well as on you), besides it wouldn't work with mod-added or generic NPCs

    Again, eager to know how it goes =D

  6. yeah, it looks like the scenes will have to be blocked manually then as in the video.

    a bit busy right now, i’ll try and test this later tonight. if i end up using the script i’ll make sure to credit you on the nexus page.

  7. Alright, I still must be doing something wrong, as I can’t get the condition to appear even after changing the property to Bool.

    So this is what i did. I made a new quest. I added the script to a new quest, just going to the script tabs and then hitting add, new script, and then copy/paste, and compile, not filling in the property. Then I go to my follower quest, DialogueFollower3DNPC, and like in the picture of this post, add a condition, GetVMQuestVariable, and the vm variable/parameter2 still has NONE as the only option.

  8. you have to select the new quest you just attached your script to.

    Parameter 1 must be the quest
    Parameter 2 must be something like “::PlayerDialogueTarget”

    and the condition must be GetVMQuestVariable PlayerDialogueTarget == 0 in order to permit talking only when not in conversation.

    Unfortunately I’ll be unavailable for a few days from now as I’ll have no internet connection. When I’m back, I’ll check here first thing. :)

  9. that just adds the words “extends quest conditional” at the top right? unless checking the box does something else i’m unaware of, as i typed the words instead of clicking it.

  10. aaaaaaaaawesome, works like a charm, but needs a condition to check if the target is your follower, or else the follower dialogue disappears while talking to them. i tried adding a line !(Target.IsInFaction(CurrentFollowerFaction)) and it compiled but it didn’t work.

  11. ah! that’s right. so the new script should look like this, where the CurrentFollowerFaction property should be filled properly. If it doesnt work i’ll open the mod here and see what i can come up with.

    —————————————————————————————————————————–
    ScriptName BARBASDialogueDetection_SCRIPT Extends Quest Conditional

    BOOL Property PlayerDialogueTarget Auto Conditional

    Faction Property CurrentFollowerFaction Auto

    Event OnInit()

    RegisterForSingleUpdate(1.0)
    EndEvent

    Event OnUpdate()

    PlayerDialogueTarget = GetPlayerDialogueTarget()
    RegisterForSingleUpdate(4.0)
    EndEvent

    Actor Function GetPlayerDialogueTarget(INT iLoopIterations = 15, Float fAreaToSearch = 350.0)

    Actor Player = Game.GetPlayer()
    Actor Target

    While iLoopIterations > 0
    Target = Game.FindRandomActorFromRef(Player, fAreaToSearch)
    iLoopIterations -= 1
    If Target && Target != Player && Target.IsInDialogueWithPlayer() && !Target.IsInFaction(CurrentFollowerFaction)
    iLoopIterations = 0
    Else
    Target = NONE
    EndIf
    EndWhile

    Return Target
    EndFunction
    —————————————————————————————————————————–

  12. okay, works perfectly. this video was before i added the fix for the currentfollowerfaction, so you can see me getting confused for a second in the middle.

    How do you want to be credited? Any other stuff you want to contribute, like getting them to ride horses or sandboxing, etcetera?

  13. credit me the way you want, i’m glad i helped ;) . as for the other things, i’ll look where to start as i’ve never really messed much with AI.

  14. ah this video probably better demonstrates it, since the first video it could’ve been zora removing the dialogue. Here it’s clear talking to Avulstein removes the follower quest, which returns when he stops babbling.

  15. now i see. i’m glad it’s working now. I love the mod. J’zargo is a great friend :D
    yes, the username is the same, ID 4521703.

  16. I would like to my 2 cents about usage of this script.

    Quoted .. “-Attach this script to a quest (any quest, really):”
    Well yes and no…

    I’d say attach it to ONE quest that is always running. It only needs to run one instance. !
    If this gets added to each and every quest it gets quite expensive on shared CPU script processing time. Especially if other modders start using this to. 100’s of quest with this script running and checking if the player is in dialogue is quite a huge over kill.

    Only problem would then be accessing the GetVMQuestVariable from other quests.
    I’d say store it in a GlobalValue so every other quest that needs to check the value can easily retrieve the value from the Global. which is also less expensive to call on each and every conditional then using getvmquestvariable.

  17. Yes, the script only needs one instance running every 4 seconds. By “Attach this script to a quest (any quest, really)” I meant that the quest the script is attached to doesn’t matter, not that he should attach it to every quest. Every mod would have to have it’s own instance of the script running so, for example, If you want to use the script on you follower mod, you’d have to make an always-running quest with the script to get the variable from.

    GetVMQuestVariable() can be accessed from any condition box, not only the ones in the quest which the script is attached to. I would avoid using globals, since they are kept stored in the savefile even after the mod is uninstalled, since the script will be always “active” (and, thus, always keeping the property there) it is better to keep it as a conditional property.

    A much more efficient script could be written if a non-auto property could be flagged as conditional, so the script would only run when the condition was called for. Sorry if I misunderstood you at any point.

  18. Script variables also gets stored in save game and stay there even if mod gets uninstalled.
    Every script and every varaible always stays in the save game. Can’t believe bethesda set it up this way.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.