NikaCola Posted January 5, 2018 Share Posted January 5, 2018 Like the title says, I'm having a little trouble using the event ondistancegreaterthan, because I need to nest it inside another event (in this instance onquestinit) What I'm trying to accomplish is that the follower I'm creating will speak a certain line once a given quest has advanced to a certain stage...but only after we're a certain distance away from the quest giver. The code I have so far looks like this...but please remember I am definitely not an expert in papyrus or any scripting so...please be gentle! =) Event OnQuestInit() RegisterForRemoteEvent(MQXXX, "OnStageSet") RegisterForDistanceGreaterThanEvent(myref1, myref2, 200.00) endevent Event Quest.OnStageSet(Quest akSender, int auiStageID, int auiItemID) if aksender == MQXXX if auistageid == XXX if MQ1 == 0 if ismyactornearPC() == true && (myref1.getreference()).getdistance(game.getplayer())>400 myactor.saycustom(xxxcustomtopic, game.getplayer()) debug.messagebox("actor should say the line") MQ1 = 1 endif endif endif endif endevent bool Function ismyactorNearPC() bool returnVal = Game.GetPlayer().GetDistance(myfollower) <= 2500 RETURN returnVal EndFunction Right now the script works as I'd like once the stage is set, but ONLY if my follower is already over the specified distance away. The problem is that there's nowhere in that block of code to put the event ondistancegreaterthan, because as near as I can tell you can only run one event at a time? I'd like for the line of dialogue to be said after the stage is set, and after the follower walks away and is a set distance away. Is there any way to make that happen that I'm missing? I'm sorry the code is so sloppy, LOL, and thank you so much for any help! <3 Link to comment Share on other sites More sharing options...
SKKmods Posted January 5, 2018 Share Posted January 5, 2018 (edited) Try an event logic structure something like this (not exact code) ... Bool bActorIsOverDistance = False Event OnDistanceGreaterThan(ObjectReference akObj1, ObjectReference akObj2, float afDistance) If akObj1 == MyActorref && mqxxx.GetCurrentStageID() >= 20 ; do stuff ElseIf akObj1 == MyActorref ; set a flag for onstageset event bActorIsOverDistance = True Endif EndEvent Event Quest.OnStageSet(Quest akSender, int auiStageID, int auiItemID) If akSender == MQXXX && auiStageID >= XX && bActorIsOverDistance == True ; do stuff Endif EndEvent Edited January 5, 2018 by SKK50 Link to comment Share on other sites More sharing options...
FlashyJoer Posted January 6, 2018 Share Posted January 6, 2018 (edited) Use 'STATES'. By using states you can have multiple EVENTS of the same type in a single script. I will refer you to the script attached to the water fountain "Vault_WaterFountain01" - script name: drinkfromfountainscript. You can see below how they are nested within OnBeginState events: State waiting ;turn off fountain (slow) when entering the waiting state Event OnBeginState(string asOldState) debug.trace(self + " OnBeginState waiting, from " + asOldState) BeginDrinking() EndEvent ;On activate start drinking Event OnActivate(ObjectReference akActionRef) debug.trace(self + " OnActivate: WAITING") If akActionRef == Game.GetPlayer() myPlayer = game.getPlayer() drinkTime = 1 amountDrunk = 1 GotoState("drinking") EndIf EndEventendStateState drinking Event OnBeginState(string asOldState) debug.trace(self + " OnBeginState drinking, from " + asOldState) ;turn on fountain (fast) SetAnimationVariableFloat("fDampRate", 0.08) SetAnimationVariableFloat("fToggleBlend", 1.0) ;wait for water flow FountainStart.play(self) utility.wait(0.25) ;drink for 1 sec (1 drinktime) ;drinkingSound.play(self) while drinkTime > 0 utility.wait(1.0) ;add spell fx for each drink spellOnDrink.Cast(myPlayer) ;play drinking sound drinkingSound.play(self) ;decrement drinktime drinkTime = drinkTime-1 endWhile utility.wait(0.5) Tutorial.SetStage(500) ; if this is furniture, loop while in it if GetBaseObject() is furniture && IsFurnitureInUse() GotoState("looping") else GotoState("waiting") endif EndEvent ;if you spam the button while drinking... Event OnActivate(ObjectReference akActionRef) debug.trace(self + " OnActivate: DRINKING") If akActionRef == Game.Getplayer() DrinkAgain() EndIf EndEventendState Edited January 6, 2018 by joerqc Link to comment Share on other sites More sharing options...
NikaCola Posted January 6, 2018 Author Share Posted January 6, 2018 Thank you for the help, and the example! I tried it out but the saycustom line fires EVERY time, no matter how close I get my follower to the objectreference (just another actor in the game.) I even tried with a ridiculous distance like 5000 but the line is immediately said once I set that quest stage. I think this is because the event is registered and fires when this particular quest starts. So the script runs and detects that my follower is far enough away from the NPC to say this line (because they haven't even met yet and are def. far away from each other at that moment) so it sets the flag to True and this doesn't really work the way I'm hoping. =( I feel like there's something so obvious I'm missing, ahh! Is there a better way to control when the event actually fires? edit: Sorry! This was a reply to SKK50. I'm looking at your example, joerqc, but for the life of me I'm really having trouble getting my head around it. =( Does using States mean I can just nest every event together, like a giant function? I've read through the CK pages on states a few times and the examples are...somewhat hard for me to follow. (again I am very very new to scripting) Link to comment Share on other sites More sharing options...
NikaCola Posted January 6, 2018 Author Share Posted January 6, 2018 Okaaay....I seemed to have gotten it working, but I think it's maybe a stupid way of doing it? The problem definitely was that the ondistancegreaterthan event was firing as soon as the quest started, and I couldn't figure out a better way to start it at the right time (on a certain quest and stage, while at the same time being able to use ondistancegreaterthan since both of these are events) So I did kind of like what SKK50 suggested, but also used another event (on scene end) to set another variable, then I waited to actually register the ondistancegreaterthan event until OnSceneEnd was done. Is that a super dumb way of doing this? I mean...it works. =D I just don't want to cause problems for the game or any one playing this mod. Here's the script as working: Event OnQuestInit() RegisterForRemoteEvent(MQXXX, "OnStageSet") RegisterForRemoteEvent(dumbprestonscene, "OnEnd") endevent Event OnDistanceGreaterThan(ObjectReference akObj1, ObjectReference akObj2, float afDistance) if akobj1 == game.getplayer() if akobj2 == dumbfacepreston if afdistance >= 500.00 if prestonscenedone == 1 if correctstage == 1 debug.messagebox ("no way this will work") myactor.saycustom(topic, game.getplayer()) Event Quest.OnStageSet(Quest akSender, int auiStageID, int auiItemID) if aksender == MQxxx if ismyactornearPC() == true if auistageid == 123 correctstage = 1 endif endif endif endif endevent event Scene.OnEnd(Scene SceneToCheck) if scenetocheck == dumbprestonscene if ismyactornearPC == true prestonscenedone = 1 debug.messagebox("stupid scene over") RegisterForDistanceGreaterThanEvent(game.getplayer(), dumbfacepreston, 500.00) endif endif endevent bool Function ismyactorNearPC() bool returnVal = Game.GetPlayer().GetDistance(myfollower) <= 2500 RETURN returnVal EndFunction Link to comment Share on other sites More sharing options...
SKKmods Posted January 6, 2018 Share Posted January 6, 2018 (edited) Considering the high level states and flow BEFORE getting stuck into the detail code is best, and from your code I infer the conditions you are working with are: Actor is close at stage start - OK 1 wait for far then 2 do stuff Actor is far at stage start - NOTOK 1 wait for close then 2 wait for far then 3 do stuff There are several ways to approach this, here is a possible function flow (this is logic not code !): OnStageSetIf stage i am interested inIs distance less than ?Yes = Set hasbeencloseflag, RegisterForDistanceGreaterThanEventNo = RegisterForDistanceLessThanEventOnDistanceGreaterThanhasbeencloseflag set ?No = RegisterForDistanceLessThanEventYes = Unregister and do stuff OnDistanceLessThanSet hasbeencloseflagRegisterForDistanceGreaterThanEvent Edited January 6, 2018 by SKK50 Link to comment Share on other sites More sharing options...
Evangela Posted January 6, 2018 Share Posted January 6, 2018 How did that even compile? The first event is not probably closed. EndEvent is missing, and those nested if statements also don't close properly. I cleaned up the syntax: Event OnQuestInit() RegisterForRemoteEvent(MQXXX, "OnStageSet") RegisterForRemoteEvent(dumbprestonscene, "OnEnd") endevent Event OnDistanceGreaterThan(ObjectReference akObj1, ObjectReference akObj2, float afDistance) if akobj1 == game.getplayer() if akobj2 == dumbfacepreston if afdistance >= 500.00 if prestonscenedone == 1 if correctstage == 1 debug.messagebox ("no way this will work") myactor.saycustom(topic, game.getplayer()) endif endif endif endif endif EndEvent Event Quest.OnStageSet(Quest akSender, int auiStageID, int auiItemID) if aksender == MQxxx if ismyactornearPC() == true if auistageid == 123 correctstage = 1 endif endif endif endevent event Scene.OnEnd(Scene SceneToCheck) if scenetocheck == dumbprestonscene if ismyactornearPC == true prestonscenedone = 1 debug.messagebox("stupid scene over") RegisterForDistanceGreaterThanEvent(game.getplayer(), dumbfacepreston, 500.00) endif endif endevent bool Function ismyactorNearPC() bool returnVal = Game.GetPlayer().GetDistance(myfollower) <= 2500 RETURN returnVal EndFunction 500 units is fairly short. That's like a few feet from an object and your logic is checking for distance greater than 500 units. What this means is anything within 500 units will fire. So you might want to try something higher. A Cell is 4096 units in width and length. So I think the following distances to try should be 1024, and 2048. Link to comment Share on other sites More sharing options...
llamaRCA Posted January 6, 2018 Share Posted January 6, 2018 So I did kind of like what SKK50 suggested, but also used another event (on scene end) to set another variable, then I waited to actually register the ondistancegreaterthan event until OnSceneEnd was done. Is that a super dumb way of doing this? I mean...it works. =D I just don't want to cause problems for the game or any one playing this mod. No, it's not a dumb way to do it. After I read your first comment I was going to suggest you register for the distance event in the onstageset event rather than onquestinit. Link to comment Share on other sites More sharing options...
ThoraldGM Posted January 7, 2018 Share Posted January 7, 2018 My Scavver NPC walks ~70 units per second. Link to comment Share on other sites More sharing options...
NikaCola Posted January 7, 2018 Author Share Posted January 7, 2018 How did that even compile? The first event is not probably closed. EndEvent is missing, and those nested if statements also don't close properly. I cleaned up the syntax: Event OnQuestInit() RegisterForRemoteEvent(MQXXX, "OnStageSet") RegisterForRemoteEvent(dumbprestonscene, "OnEnd") endevent Event OnDistanceGreaterThan(ObjectReference akObj1, ObjectReference akObj2, float afDistance) if akobj1 == game.getplayer() if akobj2 == dumbfacepreston if afdistance >= 500.00 if prestonscenedone == 1 if correctstage == 1 debug.messagebox ("no way this will work") myactor.saycustom(topic, game.getplayer()) endif endif endif endif endif EndEvent Event Quest.OnStageSet(Quest akSender, int auiStageID, int auiItemID) if aksender == MQxxx if ismyactornearPC() == true if auistageid == 123 correctstage = 1 endif endif endif endevent event Scene.OnEnd(Scene SceneToCheck) if scenetocheck == dumbprestonscene if ismyactornearPC == true prestonscenedone = 1 debug.messagebox("stupid scene over") RegisterForDistanceGreaterThanEvent(game.getplayer(), dumbfacepreston, 500.00) endif endif endevent bool Function ismyactorNearPC() bool returnVal = Game.GetPlayer().GetDistance(myfollower) <= 2500 RETURN returnVal EndFunction 500 units is fairly short. That's like a few feet from an object and your logic is checking for distance greater than 500 units. What this means is anything within 500 units will fire. So you might want to try something higher. A Cell is 4096 units in width and length. So I think the following distances to try should be 1024, and 2048. I re-wrote the script in a hurry to post it here (or at least changed the property names around a little bit) and I probably missed a few things. Thank you for cleaning it up though! I probably should get into the habit of making my stuff look like that. As for the unit distance, I was going based off this page... https://www.creationkit.com/index.php?title=Unit Is it different for fallout vs. skyrim, or have I just misunderstood how units work in general? So I did kind of like what SKK50 suggested, but also used another event (on scene end) to set another variable, then I waited to actually register the ondistancegreaterthan event until OnSceneEnd was done. Is that a super dumb way of doing this? I mean...it works. =D I just don't want to cause problems for the game or any one playing this mod. No, it's not a dumb way to do it. After I read your first comment I was going to suggest you register for the distance event in the onstageset event rather than onquestinit. That makes me feel at least somewhat less stupid, thank you! =D Link to comment Share on other sites More sharing options...
Recommended Posts