Talk:Activation Functions

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search

"There appears to be some kind of recursion catch that stops calls working if the same script is called within the same frame more than ~4 times." Guidobot, is this only true for recursion? I've not had any problems so far with 100s of activations (and yes, I need them), so long as it's another script calling the activator, and not the activator calling itself. Are there special circumstances?
--Haama 04:40, 12 July 2007 (EDT)

I assume that the limit is put there as a recursion catch but it is active no matter how the object script is called within the same frame, e.g. having multiple Activate/PlaceAtMe lines in a single script or in multiple scripts running in the same frame. This also applies to scripts on objects placed in the game. For example, when you have 4 or more scripted skeletons some will appear to freeze/lag.
--Guidobot 20:11, 9 September 2007 (EDT)
I've done a bit more testing since then (see Activate), and as far as I can tell it's only true of recursion (not sure about the skeleton thing, though). One of my mods, Inventory Tracker, activates a single activator 1000 times a frame without any problems (reported, or in tests). The recursion limit also seems to be limited to the onActivate block, as I've run over 250 quest result scripts from within each other (again, see Inventory Tracker). I've also done some tests with mixes of result scripts and onActivate blocks, and 'SomeObject.Activate player, 1' won't run if and only if there are 3-4 other onActivate blocks running at the time (not, in the same frame). I'd have to dig those tests up, though.
Also, I have found that you can constantly load a remote activator (make it run every frame as if it were moved to the player) by changing a variable on the activator. It hasn't been throughly tested, but maybe it should be included?
--Haama 18:34, 10 September 2007 (EDT)
Interesting, but becareful about what you assume about the generality of 'activators'. I am still suspect about expecting an activator to be callable 1000 times in the same frame, especially if the OnActivate script is of any length. If this is true then you should be able to generate visible lag very easily (even w/o inventory redraws, etc.).
--Guidobot 12:27, 13 September 2007 (EDT)

Not at all, I don't see any FPS drop until I run it 2000 times, and even then it's only 1 FPS. What seems to be important are the functions used, not the number of lines. Here's the script:

scn ITNumCheckerScript



ref   pItem
short ItemCount
short TempItemCount
short DiffNum

short InvPos
short LinkedListTotal
short LinkedListPos



begin onActivate
	set LinkedListPos to (LinkedListPos + 1) 
	if pItem
		set TempItemCount to (player.GetItemCount pItem)
		
		if TempItemCount
			set InvPos to (InvPos + 1)
		endif
	
		if (TempItemCount == ItemCount)
			return ;Don't need to worry about changing ItemCount, it's the same as TempItemCount
		elseif (TempItemCount < ItemCount) ;Lost Quantity
			SetStage ITInvChangesDecreasedList 0
			SetStage ITInvChangesRemovedList 0
ITInvChangesRemovedList.Changes
			
		else ;if (TempItemCount > ItemCount) ;Gained Quantity
			SetStage ITInvChangesIncreasedList 0
			SetStage ITInvChangesAddedList 0
		endif
		
		set ItemCount to TempItemCount
	
	
	;Setup new spot if needed
	elseif (LinkedListPos > LinkedListTotal)
		set pItem to (player.GetInventoryObject InvPos)
		if (pItem == 0) ;No more items
			set ITListManager.Counter to 254 ;Wraps everything up
			return
		elseif (ITLinkedListCont.GetItemCount pItem) ;If the player has picked up an item(s) that they've already picked up, then it won't be in the expected position above, and instead an item that's already in the linked list will be referenced, so check against a container full of linked list items
			ITInvScanner.Activate player, 1
			if (pItem == 0) ;No more items - just in case
				set ITListManager.Counter to 254
				return
			endif
		endif
		set LinkedListTotal to (LinkedListTotal + 1)
		ITLinkedListCont.AddItem pItem 1
		set ITInvChangesNewList.Changes to (ITInvChangesNewList.Changes + 1)
		SetStage ITInvChangesNewList ITInvChangesNewList.Changes
		
		
		set TempItemCount to (player.GetItemCount pItem)
		
		if TempItemCount
			set InvPos to (InvPos + 1)
		endif
	
		if (TempItemCount == ItemCount)
			return ;Don't need to worry about changing ItemCount, it's the same as TempItemCount
		elseif (TempItemCount < ItemCount) ;Lost Quantity
			SetStage ITInvChangesDecreasedList 0
			SetStage ITInvChangesRemovedList 0
			
		else ;if (TempItemCount > ItemCount) ;Gained Quantity
			SetStage ITInvChangesIncreasedList 0
			SetStage ITInvChangesAddedList 0
		endif
		
		set ItemCount to TempItemCount ;this will leave pItem's that have been nullified with a random number, this might matter if the ref is actually remembered past a mod being uninstalled and reinstalled
	endif
end

--Haama 16:12, 13 September 2007 (EDT)