ZeroCore Posted July 5, 2016 Share Posted July 5, 2016 I had an idea for an object that, when brought into the game via another object using "PlaceAtMe", would use the "OnInit" event to start a "utility.wait" timer, and at the end of this timer would delete itself. The thing of it is though is that I have no idea how to get an object/activator to perform a script on itself, and the "delete" function is a bit difficult for me to understand. Can someone please explain how to use this? The wiki wasn't much help. Link to comment Share on other sites More sharing options...
Ghaunadaur Posted July 5, 2016 Share Posted July 5, 2016 That should work. The OnInit event will get called when the reference is created by the PlaceAtMe function. A short script like this may do it: Scriptname yourscriptname extends ObjectReference Event OnInit() Utility.Wait(10.0) ;will wait for 10 seconds self.Delete() EndEvent ...also possible to register for an OnUpdate event and delete itself after a given time. Scriptname yourscriptname extends ObjectReference Event OnInit() RegisterForSingleUpdate(10.0) EndEvent Event OnUpdate() Delete() EndEvent You would need to attach the script to the base object. Link to comment Share on other sites More sharing options...
ZeroCore Posted July 5, 2016 Author Share Posted July 5, 2016 (edited) That should work. The OnInit event will get called when the reference is created by the PlaceAtMe function. A short script like this may do it: Scriptname yourscriptname extends ObjectReference Event OnInit() Utility.Wait(10.0) ;will wait for 10 seconds self.Delete() EndEvent ...also possible to register for an OnUpdate event and delete itself after a given time. Scriptname yourscriptname extends ObjectReference Event OnInit() RegisterForSingleUpdate(10.0) EndEvent Event OnUpdate() Delete() EndEvent You would need to attach the script to the base object. I tested the script, the activator spawns in, but when it goes to delete itself I get a Crash-To-Desktop. I'm not sure what's going wrong here. Does it matter that the type of activator that I'm using is a water plane? Could that be the issue? I think I may have fixed the issue; I take it the game doesn't like it when you try to delete something that's loaded, so what I did was I added a pair of lines that makes the activator disable itself prior to deletion, and it stopped the crashing: Scriptname yourscriptname extends ObjectReference Event OnInit() RegisterForSingleUpdate(10.0) EndEvent Event OnUpdate() Disable() utility.wait(1.0) Delete() EndEventI have another question, if that's okay; can you adjust the Z position or any other positions of an object called in with "PlaceAtMe"? What I want to be able to do is to have the lever that spawns in the object spawn it in at a height offset, namely I want to have it spawn in at the coordinates of, "akActivator.GetPositionZ() + 20" when an activator is activated. I was thinking of using MoveTo; Scriptname AAAPlaceAtPlayerWaterScript extends ObjectReference Activator Property waterplane Auto Event OnActivate(ObjectReference akActivator) akActivator.placeAtMe(waterplane, 1, false, false) waterplane.MoveTo(0, 0, akActivator.GetPositionZ() + 20) EndEventbut I keep getting this error: "MoveTo is not a function or does not exist." Edited July 5, 2016 by ZeroCore Link to comment Share on other sites More sharing options...
Ghaunadaur Posted July 5, 2016 Share Posted July 5, 2016 (edited) I forgot about the disable part. Glad you got it fixed.I think MoveTo is the right function to use here, but you can't do that with the base object.At first you'll need to obtain the reference you just placed in the world, and move this. Scriptname AAAPlaceAtPlayerWaterScript extends ObjectReference Activator Property waterplane Auto Event OnActivate(ObjectReference akActivator) ObjectReference ActivatorRef = akActivator.placeAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(akActivator, 0.0, 0.0, 20.0) EndEvent Edited July 5, 2016 by Ghaunadaur Link to comment Share on other sites More sharing options...
ZeroCore Posted July 5, 2016 Author Share Posted July 5, 2016 (edited) I forgot about the disable part. Glad you got it fixed. I think MoveTo is the right function to use here, but you can't do that with the base object. At first you'll need to obtain the reference you just placed in the world, and move this. Scriptname AAAPlaceAtPlayerWaterScript extends ObjectReference Activator Property waterplane Auto Event OnActivate(ObjectReference akActivator) ObjectReference ActivatorRef = akActivator.placeAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(akActivator, 0.0, 0.0, 20.0) EndEvent This script works. Thanks. There's one last thing I need to know; in a script that begins with the "OnEquipped" Event, how do you make the script recognize the equipped item that the script is attached to? To make a long story short, you've got a ring with a script that is supposed to perform a pre-test "while" loop. The loop's condition is that the player has the same ring the script is attached to equipped. How do I get the ring's reference and pass it to the loop? A possible way to do this, I think, might be to do something like this: Scriptname AAARingScript extends ObjectReference Int SwitchInteger Event OnEquipped(Actor akActor) SwitchInteger = 1 RegisterForSingleUpdate(0.5) EndEvent Event OnUnEquipped(Actor akActor) SwitchInteger = 0 UnregisterForUpdate() EndEvent Event OnUpdate if SwitchInteger == 1 ;do something... RegisterForUpdate(0.1) endif EndEvent I have no idea if this will work or not. There probably is a more elegant way to go about this too, but right now I have no idea what that is. There's also the issue that I really want to combine the two scripts. Essentially once the ring is equipped, it does the script that you listed for me before (the one that I modified to include the "disable" function). The ring would continuously spawn those self-deleting water planes below the player, or rather below anyone who has the ring equipped. Edited July 5, 2016 by ZeroCore Link to comment Share on other sites More sharing options...
IsharaMeradin Posted July 5, 2016 Share Posted July 5, 2016 You can use self to target the script running and cast that as ObjectReference to get the specific reference running the script. So... ObjectReference MyEquippedRing = Self as ObjectReference But even if you use the script multiple times on multiple objects, it only runs for that particular object. So if you register for an update with one object, only that object's script will perform the update. What you have should be fine even without the SwitchInteger variable you put in there (unless you need that for something else). Why? Because when you unregister for the update when the item is unequipped, it won't perform the next update. Link to comment Share on other sites More sharing options...
Ghaunadaur Posted July 5, 2016 Share Posted July 5, 2016 As IsharaMeradin pointed out, each script instance will only run for the object reference it's attached to. Additionally, if you want to call a function on "self", you don't even need to write out that variable. So for example, instead of self.SomeFunction(), you can just write SomeFunction().I'm not sure if I got everything right what you are trying to do, but I would rather suggest to combine the second and the third script, and leave the first one on the activator to disable and delete itself. OnUpdate event should work fine for this purpose, I don't see any need for a While loop.The script could look like this: Scriptname AAARingScript extends ObjectReference Activator Property waterplane Auto Actor SomeActor Event OnEquipped(Actor akActor) SomeActor = akActor RegisterForSingleUpdate(1.0) EndEvent Event OnUnEquipped(Actor akActor) UnregisterForUpdate() SomeActor = none EndEvent Event OnUpdate() if SomeActor ObjectReference ActivatorRef = SomeActor.placeAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(SomeActor, 0.0, 0.0, 20.0) RegisterForSingleUpdate(1.0) endif EndEvent (The current script should work with anyone who equipped the ring, not only the player.) Link to comment Share on other sites More sharing options...
ZeroCore Posted July 6, 2016 Author Share Posted July 6, 2016 (edited) You can use self to target the script running and cast that as ObjectReference to get the specific reference running the script. So... ObjectReference MyEquippedRing = Self as ObjectReference But even if you use the script multiple times on multiple objects, it only runs for that particular object. So if you register for an update with one object, only that object's script will perform the update. What you have should be fine even without the SwitchInteger variable you put in there (unless you need that for something else). Why? Because when you unregister for the update when the item is unequipped, it won't perform the next update. As IsharaMeradin pointed out, each script instance will only run for the object reference it's attached to. Additionally, if you want to call a function on "self", you don't even need to write out that variable. So for example, instead of self.SomeFunction(), you can just write SomeFunction(). I'm not sure if I got everything right what you are trying to do, but I would rather suggest to combine the second and the third script, and leave the first one on the activator to disable and delete itself. OnUpdate event should work fine for this purpose, I don't see any need for a While loop. The script could look like this: Scriptname AAARingScript extends ObjectReference Activator Property waterplane Auto Actor SomeActor Event OnEquipped(Actor akActor) SomeActor = akActor RegisterForSingleUpdate(1.0) EndEvent Event OnUnEquipped(Actor akActor) UnregisterForUpdate() SomeActor = none EndEvent Event OnUpdate() if SomeActor ObjectReference ActivatorRef = SomeActor.placeAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(SomeActor, 0.0, 0.0, 20.0) RegisterForSingleUpdate(1.0) endif EndEvent (The current script should work with anyone who equipped the ring, not only the player.) I tried that script, and it didn't work. I put the ring on, and nothing happened. The waterplane property was filled out correctly too; I checked. I tried a bit of a modification to the script, but it won't work either. The script I used was: Scriptname AAAFlightRing extends ObjectReference Activator Property waterplane Auto Actor Property Wearer Auto Actor Wearer Event OnEquipped(Actor akActor) Wearer = akActor RegisterForSingleUpdate(1.0) EndEvent Event OnUnEquipped(Actor akActor) UnregisterForUpdate() Wearer = none EndEvent Event OnUpdate() float ViewAngle = Wearer.GetAngleX() if Wearer ObjectReference ActivatorRef = Wearer.placeAtMe(waterplane, 1, false, false) ActivatorRef.SetAngle(0, 0, 0) ActivatorRef.SetScale (6) if ViewAngle < (-30) ActivatorRef.MoveTo(Wearer, 0.0, 0.0, -5.0) elseIf ViewAngle >= (-30) && ViewAngle <= (30) ActivatorRef.MoveTo(Wearer, 0.0, 0.0, -1.0) elseIf ViewAngle > (30) ActivatorRef.MoveTo(Wearer, 0.0, 0.0, 5.0) Wearer.MoveTo(ActivatorRef, 0.0, 0.0, 1.0) endif RegisterForSingleUpdate(3.0) endif EndEvent For some reason when I put the ring on, it doesn't do anything. What I'm trying to get it to do is to have the activator "waterplane" be placed at a certain height which is altered by the player's vertical look angle. Then I tried doing this: Scriptname AAAFlightRing extends ObjectReference Activator Property waterplane Auto Actor SomeActor Event OnEquipped(Actor akActor) debug.notification("script") SomeActor = akActor ObjectReference MyEquippedRing = Self as ObjectReference While SomeActor.IsEquipped(MyEquippedRing) ObjectReference ActivatorRef = SomeActor.placeAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(SomeActor, 0.0, 0.0, -0.5) utility.wait(3.0) EndWhile EndEvent This didn't work either. I stuck the debug notification on there to see if it would even do anything. It did get that far at least. I saw the debug message appear on my screen's top-left corner. The issue is though is that it won't enter into the while loop and I have no idea as to why. Edited July 6, 2016 by ZeroCore Link to comment Share on other sites More sharing options...
Ghaunadaur Posted July 6, 2016 Share Posted July 6, 2016 (edited) I believe the reason as to why it's not working is being the ring in a container. According to the wiki it would work with a persistent reference. I did some testing as well, following the methods to make an item persistent as described here and here. Shortly said, nothing I tried did work, when using the OnEquipped event. I'm afraid you will need to make this in a different way: 1. Create a quest that starts game enabled. 2. In the aliases tab of the quest, make a ReferenceAlias and fill it with the player actor as unique actor. 3. Place the following script on the ReferenceAlias: Scriptname yourscriptname extends ReferenceAlias Armor Property Ring Auto Activator Property waterplane Auto Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) if akBaseObject == Ring Utility.Wait(0.5) RegisterForSingleUpdate(1.0) endif EndEvent Event OnUpdate() ObjectReference ActivatorRef = GetActorReference().PlaceAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(GetActorReference(), 0.0, 0.0, 20.0) RegisterForSingleUpdate(1.0) EndEvent Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference) if akBaseObject == Ring UnregisterForUpdate() endif EndEvent On another note, using a while loop with a placeatme function that fills the surrounding area with countless of references, is probably not a good idea, even if they're deleted short time after. It may lead to a performance decrease in the game. By registering for an OnUpdate event, you can adjust the interval the objects are getting placed and deleted. That seems preferable to me. Edited July 6, 2016 by Ghaunadaur Link to comment Share on other sites More sharing options...
ZeroCore Posted July 7, 2016 Author Share Posted July 7, 2016 (edited) I believe the reason as to why it's not working is being the ring in a container. According to the wiki it would work with a persistent reference. I did some testing as well, following the methods to make an item persistent as described here and here. Shortly said, nothing I tried did work, when using the OnEquipped event. I'm afraid you will need to make this in a different way: 1. Create a quest that starts game enabled. 2. In the aliases tab of the quest, make a ReferenceAlias and fill it with the player actor as unique actor. 3. Place the following script on the ReferenceAlias: Scriptname yourscriptname extends ReferenceAlias Armor Property Ring Auto Activator Property waterplane Auto Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) if akBaseObject == Ring Utility.Wait(0.5) RegisterForSingleUpdate(1.0) endif EndEvent Event OnUpdate() ObjectReference ActivatorRef = GetActorReference().PlaceAtMe(waterplane, 1, false, false) ActivatorRef.MoveTo(GetActorReference(), 0.0, 0.0, 20.0) RegisterForSingleUpdate(1.0) EndEvent Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference) if akBaseObject == Ring UnregisterForUpdate() endif EndEvent On another note, using a while loop with a placeatme function that fills the surrounding area with countless of references, is probably not a good idea, even if they're deleted short time after. It may lead to a performance decrease in the game. By registering for an OnUpdate event, you can adjust the interval the objects are getting placed and deleted. That seems preferable to me. So there is no way to make this usable for an NPC? You have to make a quest that will only accept the player as a persistent reference? Also, how does this thing know what ring to use? Will this script trigger whenever ANY ring is equipped? How does it tell what ring will trigger the script? Ugh... There's way too much about this scripting language that I just don't know, that the tutorials don't teach you, and that very few are willing to tell you about. I still really want this ring, or at least a spell or something, to be able to do this script and have it work for anyone who casts it, player or NPC. Is there a script command that can place an actor (such as the wearer) into an alias for a quest, or that can create an alias in a quest and then force said actor into it? Edited July 7, 2016 by ZeroCore Link to comment Share on other sites More sharing options...
Recommended Posts