Talk:Activate

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search

Rewrite[edit source]

Is it just me, or is a lot of Kkuhlmann's information here wrong? Activate blocks are done when called, not later, correct?
Dragoon Wraith TALK 10:54, 13 July 2007 (EDT)

You can actually tell who's saying what??? Yeah, that information is incorrect on activating (not quite sure about onUnEquip, I'd say yes but I have one more thing to test). An activation runs the entire onActivate block (be it another object or that object) before the next line of code is processed. Not quite sure about "Atomic" and having multiple onActivate blocks in a script though (mainly because it hurts to think about why one would do that...). Also, this article is really confusing. Really, really, really confusing and since it doesn't mention that the reference is the object that's activated, it borders on useless. *sigh* I need to say more about it, but what's keeping me from rewriting the whole article - I don't want to turn it into a different structure/flow from other function articles, and I simply haven't read all of them. (I am more than happy to run tests, though - hence the nesting section)
--Haama 12:58, 13 July 2007 (EDT)
On the Wiki, correct information > consistent formatting. Feel free to fix this any way you like. If necessary, I can re-format what you write to make it consistent. I simply don't know enough about the intricacies of this function to write it myself. You might want to have a look at OnActivate, too.
Dragoon Wraith TALK 15:53, 13 July 2007 (EDT)
Wow, just wow... I'll start working on both of them. There are some things I just don't know, though - for instance, what will Activate SomeRandomNPC do? Does a simple Activate really assume the "Activator's 'current ActivatorID'" (rewritten as "Activator's ActionRef") or does it assume the player? Also, this is a unique case, as the ActivatorID is required if you use the RunOnActivateFlag, but optional if you don't (well, again, does it actually do anything for normal activation?)
--Haama 17:54, 13 July 2007 (EDT)
One part that's somewhat right - a foreign object does get flagged for 'onAdd' blocks, but I don't think the flag is on the object (because it won't run if you then move it to the player), but instead the flag is set on the cell (because the script will run once you enter that cell, even if the object is somewhere else)
--Haama 13:02, 13 July 2007 (EDT)
Would a good test be to 1st move that object to the player, then move the player to the cell where the object was? If that's true, then the object would have its onAdd block do the stuff (if not, then move the object back to the cell where you've moved the player - its originasl cell-, and see what happens)...?
--HawkFest 21:30, 16 April 2008 (EDT)

Syntax[edit source]

Alright, so that's how it should look now? This is based on discussions on the Terminology Discussion thread on the Elder Scrolls Forums and Wrye's Modding Terminology paper. Some parts are pretty much finalized, some is still up in the air, so please continue the discussion in the Community Portal.
--Haama 20:20, 14 July 2007 (EDT)

Syntax Question[edit source]

This page is unclear, does player.Activate doorID mean the player activates the door, or the door activates the player?

--Kkuhlmann 12:04, 6 April 2006 (EDT): What you wrote means the door is activating the player. If you want to simulate the player activating a door: DoorID.Activate player

Scripting Issues[edit source]

--Mrflippy 12:59, 12 April 2006 (EDT) I've been having some issues with this command in scripts. Sometimes, "object.activate me, 1" just doesn't work. The OnActivate block in the script attached to object isn't run at all. Most of the activators I work with are dynamically created using PlaceAtMe. Is this the source of the problem?

--Tegid 13:37, 12 April 2006 (EDT) I too am having this problem. Is there some kind of time constraint on activation? What causes them to just not activate? If they are already inside their OnActivate block and someone calls Activate on them, what happens then?

--Kkuhlmann 14:01, 12 April 2006 (EDT): Some things to keep in mind which could be causing your issues:

  • All "action" block types (OnActivate, OnEquip, OnAdd, etc.) work by setting a flag on the script when the action occurs. The next time the script runs, if the appropriate block flag is set, that block is executed, and the flag is reset (so it doesn't run it more than once for a single action).
  • Object scripts only run if the object is in the currently loaded area -- where the player is. So calling Activate on something that isn't loaded will set the flag for that action, but won't actually trigger the script (it will trigger the next time the object's script is run). NPC scripts (on persistent NPCs) do run when they're not loaded, but only when their AI is updated, which can happen as infrequently as every 15 game minutes.

--Tegid 15:13, 12 April 2006 (EDT) So three questions.

  • That reset happens when the OnActivate block starts or stops? (So if I send another activate before it is finished with its block, will it be cleared when its block ends and therefore never happen?)
    --Kkuhlmann 08:49, 14 April 2006 (EDT): Reset happens when the script is finished processing. So calling Activate on an object from within its own script won't work.
I don't understand what you mean: what "reset" are you referring to? Cell reset? Fact is that MANY objects actually can have an Activate command within their own onActivate script, and more over MUST have one so as to activate themselves, especially those objects involving a GUI presented to the player in menu mode (like beds, containers and such)!... But of course, this Activate command will NOT "reactivate" a second pass of the onActivate script, it will instead render the default activation behavior of the object.
--HawkFest 21:39, 16 April 2008 (EDT)
Don't know about the reset, but I believe they're referring to an item activating itself with the onActivate flag. Yes, this can be done, but no, it shouldn't be done (just copy the code for each) and can lead to CTDs if not done carefully.--Haama 00:47, 17 April 2008 (EDT)
  • As long as I've used PlaceAtMe to create this object, the second section shouldn't apply correct?
    --Kkuhlmann 08:49, 14 April 2006 (EDT): Rephrase the question to be more specific. I don't understand what you're asking.
    --Tegid 09:32, 14 April 2006 (EDT):Since I'm using PlaceAtMe, the object will always be in my cell and therefore will always run it's activate script.
  • Are script blocks atomic?
    --Kkuhlmann 08:49, 14 April 2006 (EDT): I don't know that I understand what you're asking. You CAN have more than one script block of the same type in a script -- since the flags are cleared at the end of the script, any number of blocks of the same type can exist in the script just fine. Why you'd want to do this, I don't know. But you could. If that's what you were asking.
  • --Tegid 09:27, 14 April 2006 (EDT): By Atomic I mean, does the entire script block (or script) execute without interruption by another script, or can it be interrupted by another script mid-run and then come back and finish later?

Nesting[edit source]

--Tegid 00:40, 26 April 2006 (EDT) With MrFlippy's help, I believe I have found an issue with chained activations. If I have more than four objects which pass a single Reference down an activate chain, after the fourth pass, my reference is normally != to what it was when it started down the chain. (It does SOMETIMES make it to the 5th object). As an example.

scn Object1Script
ref incoming

begin OnActivate
  set incoming to GetActionRef
  if (incoming == SomePresetReferenceInAPersistentObject)
    Message "I am doing something cool in Object 1",1
  endif
  Object2Ref.Activate incoming 1
end

if Object2Ref has a script that is similar but activates Object3Ref like so

scn Object2Script 
ref incoming

begin OnActivate
  set incoming to GetActionRef
  if (incoming == SomePresetReferenceInAPersistentObject)
    Message "I am doing something cool in Object 2", 1
  endif
  Object3Ref.Activate incoming 1
end

And so on down to Object5, object 5 will NOT execute the code inside its if statement. That equality will evaluate to false. Am I missing something, or is this a bug based on something you couldn't imagine us wanting to do?

I've posted a test showing that you can, normally, have 5 called nested scripts running at once (6 including the original, calling script). It also shows you can't avoid the limitation by using a result script to call the activator.--Haama 05:28, 30 July 2008 (EDT)

Fake "Nesting"[edit source]

  • At the bottom of the article, "Nesting" section, it is written:
You can only nest 5-6 activations at a time. At a time is a little hard to define here, since OnActivate blocks run instantly and before the next line of code is processed. This really means that if 4 other scripts are still being processed and an activation is made during the 5th script, that last activation will be ignored (the script skips the line). This applies to any activation, even if they're different objects or different scripts.
Maybe that you problem is due to some limit imposed by the engine over piling (or stacking) onActivate processes : since the onActivate block executes fully before going on to the next line of code, a stack is taking place here, as would do a recursive method... As such using the GameMode block that executes every frame would be more appropriate imho, given the provision of some conditional control to recreate what you want to do. Be aware to put any onActivate control block before the GameMode block for any reference involved in the chain, and which could serve as some "State observer" setting variables controling its GameMode block - and thus a chain of events that could involve multiple object references/path/scenario/story lines/effects/whatever... I'd try this using tokens instead of the actual objects needed to be manipulated during the chain of events (the scripting of these object staying thus independent from the FX or the wanted "chain reaction" in itself, making them consequently and independently reusable for some other stuff you could want them to do or behave in another stage or scenario). Note that I am not talking about an "instantaneously chained" multiple events triggered via onActive blocks - at most 4 to 5 considering what you said (which would be "normal" in regards to the "fps factor" during game playing)-, but about a chain reaction happening frame-by-frame (you could mix both methods btw). Although the later is only based over logical assumptions in regards to all the info provided around, maybe I'll try this some other time in a mod, as a "proof of concept"... --HawkFest 23:54, 11 September 2007 (EDT)
I've done it. A hint to the simplest way, not only to do it, but also to manage it: from a quest script or another object's script, use/set object variables that are triggering your stuff, exactly when you want it... set refObjectID.localVar to 1, where a conditional block on localVar, within the refObjectID's GameMode block script, would trigger whatever stuff you wish for it to render. Like a "Master script" that is managing the cascading events from one single object's script that is NOT involved into that chain reaction (which object can be hidden in the player's cell, or that would have no other use than showing itself as well as doing this "orchestration" silently). --HawkFest 21:54, 16 April 2008 (EDT)

True, this can be done, but it's not really nesting. Nesting means everything runs before the next line of code runs - this avoids a good chunk of timing issues ("orchestration") and would be much prefered.--Haama 05:28, 30 July 2008 (EDT)

I was thinking about this, and I was wondering what situations would really call for nesting 5-6 levels deep? I think generally better practice would be to have most activator scripts do something and then return, rather than call another activator mid-script. Most things that can be done via deep nesting can also be done relatively painlessly via simple nesting. So again, I'd be interested to see examples of where deep nesting would be used and for what.
--quetzilla 06:13, 10 August 2008 (EDT)
Then check out the COBL Functions or RUE. For the functions, there are basically two issues: I never know how deep the nest is when a modder calls them, and there are small parts of the script, like refreshing the container or player's inventory, that I expect to update (better method, OBSE function, etc.). For RUE, well... RUE is pretty freakin' complex and I had to condense a few scripts because I went over the nesting limit. The recipe (cobRUERecipeEnchScrollOS) calls the Open Recipe function (cobRUEOpenRecipeFAS) which calls...--Haama 10:34, 10 August 2008 (EDT)
Okay I see what you mean, for when your functions are intended to be used by other mods and so you don't know how deep the nesting is yet.
--quetzilla 21:19, 11 August 2008 (EDT)

RunOnActivateBlock Flag[edit source]

This flag seems to determine more than whether to run the onActivate block or not; it appears to be more of a DoNormalActivation flag (which includes running the script if it's present), than simply a RunOnActivateBlock flag.

Example: Steal an unscripted item, and drop it. If you pick it up again, your stolen item misc count will NOT increase (since you already stole it once). Now, take the same item, and instead of picking it up, target it in the console and do "activate player". The stolen item misc count increases. If you use "activate player 1", the stolen item misc count will NOT increase. Since the item is unscripted, you wouldn't expect the RunOnActivateBlock flag to actually do anything. --Waruddar 15:24, 1 February 2008 (EST)

Well, that's bizarre. Good find... I have no idea why that would be.
Dragoon Wraith TALK 16:15, 1 February 2008 (EST)
My best guess would be that the absence of the flag is actually telling the engine not to parse the ExtraData (stolen status, scripts, item health, etc) on the item. If it doesn't read that data, then the engine doesn't know to run any scripts or that you already stole the item. Then again, in order to erroneously increment the theft count, it has to read some part of that data to know that it was stolen at all. --Waruddar 18:00, 1 February 2008 (EST)
But then the engine wouldn't know that the item was stolen in the first place, since that's also ExtraData, no?
Dragoon Wraith TALK 18:17, 1 February 2008 (EST)
Yeah, that's the kink in that theory. If the theory is true, then the fact that it checks the stolen status is a bug (likely an overlooked check in a sub function). If the theory is false, then I have absolutely no idea. Regardless, there's little chance of proving any of this. Waruddar 19:45, 1 February 2008 (EST)
Well actually it makes perfect sense in regards to your theory... Unless: have you tried picking up the item before doing it in-game for the 1st time (from the console and without the flag)? Logically it should not increment the theft count if your theory is correct. --HawkFest 03:37, 5 February 2008 (EST)

I have found that picking up items with the RunOnActivateBlock = 0 leaves data behind, bloating the savegame (reported here - and I must say that the text above was most fundamental to my tests).

Now I found that the statement about activating unscripted items (item 3 under "Buggy Bug Bug of a Weird, Weird Bug") is only true if activating it with RunOnActivateBlock = 0:

  • Containers: as the article says - you cannot 'open' them anymore
  • Dynamic carryable items - Everything works, but bloats the savegame
  • Non-dynamic carryable items - if picked up with "Item.activate player 0", after dropping it later on, the item will not respond to spacebar 'pick up' (you can still move it with the grab key).

Building up on Waruddar's guess, it seems that the engine not only doesn’t parse the ExtraData, but also messes up the data structure for that particular FormId (or skips something that should be done), so the next time you activate a non-dynamic reference (same FormId) it will not respond as expected. Dynamic items, themselves, don’t suffer the consequences of this bug (?), as they always get a new, fresh FormId (but, as mentioned, the old, useless data will remain in the game).

I wonder if there is any reason at all to use the Activate function with the RunOnActivateBlock set to 0. QQuix 11:10, 28 February 2009 (EST)

Good to know, QQuix. To answer your question - you would want to run an Activate without the Run flag from an object's own script (i.e., scripted cupboard opening upon correct answer to a riddle). Not sure if it creates the same bug, though.
--Haama 14:09, 28 February 2009 (EST)
Ooops . . . forgot about that. A few more tests:
  • A plain activate within the OnActivate block does not break the item (as, of course, the item has an OnActivate block).
  • Containers: using Activate within its own gamemode block seems to have the same effect as if activated from other script:
  • 'Activate' - does not break the container, but does not open it either.
  • 'Activate player 0' without an OnActivate block - opens the container once, but breaks the container for further activations.
  • 'Activate player 1' - works OK
The bottom line seems to be that RunOnActivateBlock = 1 always works and RunOnActivateBlock = 0 only works if the activated object has an OnActivate block. (I am adjusting the article)
Therefore, recommendation could be:
  • Use RunOnActivateBlock = 0 only if you know for sure the object has an OnActivate block and, for some reason, you don't want that block code to run.
  • Use RunOnActivateBlock = 1 otherwise, especially when activating items you are not familiar with (cell scan, spell effects, etc)
QQuix 16:59, 28 February 2009 (EST)

Can't activate while on a horse[edit source]

Seems that actors on horseback won't activate anything and can't be used for the ActivatorID--Haama 01:23, 3 April 2008 (EDT)

Belated confirmation - I believe you can get around it by placing an actor in a Remote cell, leave it Enabled, and use that actor's reference editorID instead of player.

Weird Bugginess ![edit source]

It seems as objects should not activate objects. [1]. Needs some more confirmation - shadeMe TALK 17:17, 9 June 2009 (EDT)

Activating an object every frame[edit source]

After some extensive tests I came to the conclusion that using the Activate functions prevents further scripts from running in the same frame. The script with the Activate function executes to the end normally. This is consistently repeatable in my game setup.

I suppose it needs confirmation from other modders in order to add it to the article, but I think it is a general problem as there is a warning in the Common Bugs article.

Therefore, using an Activate functions every frame may cause other scripts not to run. This is particularly bad in scripted objects in the player's inventory because, as the player walks around, the game may present some strange behavior (because some scripts are not running). Example (just tested): when watching an arena match from the balcony, when one of the combatants dies, the announcer does not come in. If the script stops using the Activate function, the announcer announces the winner and the game continues normally

I also concluded that, in exteriors, the game engine looks for scripted objects in a given order: from South to North and from West to East. Example: supposing the player is in cell 3-13 and, therefore, the 25 cells around the player are loaded. Scripts in cell 1-11 are executed first, then the ones on cell 2-11, then 3-11, 4,11 and 5,11. Since cell 6,11 is not loaded, the engine executes scripts in the next 'column'? 2-11, 2-12 … 2-15. Then 3-11 thru 3,15 and so forth until cell 5-15.

Supposing there is a scripted object in each of those cells, if any of them uses an Activate function, no other script down the line (North and East) will execute in that frame.

A little more details in the Beth Forum thread: Scripts stop running as the PC enters the cell

OBSE's Activate2 does not cause this problem.

MoveTo also causes exactly the same problem, as reported by flippantremark in this Beth Forums thread: Beth Forums thread: Help needed - moving lightsource scipt

QQuix 22:08, 14 July 2009 (EDT)

Odd bug when used on a door[edit source]

I am trying to run an activate on a door once a questvariable has reached a specific value.

This is the script (Quest):

Short TrollGate

Begin GameMode

If TrollGate == 4
  NexusTrollGateRef.Activate
  Set TrollGate to 5
Endif

And "TrollGate" is increased by 1 every time the player activates a specific activator. Now, based on this, everything should really work, and it has done before, but the odd thing is: If I try to activate the activators, the door won't open, but if I try to first activate the door by hand, which will then give me a message saying I can't open it, and then try to activate the activators, the door opens. Zaldir 14:13, 11 September 2011 (EDT)

Not really sure what you're describing, to be honest, but I don't know of any oddities with doors. You may have better luck on the Forums for a question like this; there isn't a lot of activity on the Wiki, sadly. It would be appreciated if you reported back or updated the page if you discover what the problem is!
Dragoon Wraith TALK 23:12, 11 September 2011 (EDT)