Difference between revisions of "Activation Functions"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>Guidobot
(put script back to correct)
imported>Guidobot
(update of old text)
Line 2: Line 2:




This is an alternative to using stage functions.
In-game functions are basically scripts on objects (placed in the game) that can be called from any other script. You can also pass variables in and out of that function easily without reference to independent global variables.
It relies on the fact that the Activator method can be called on a persistant object at any time and operates immediately.


In-game functions are easier to create. They also do not have the restrictions that Stage functions have (number of lines, refernce object calls, variable definiton, etc.) and allow for looping code through clever use of the additional GameMode block (using flags, counters, etc.). Additionally, they are an alternative way to add global variables to the game.
In-game functions are easier to create and do not have the restrictions that Stage functions have, e.g. number of lines, reference object calls, variable definiton, etc. You can do almost anything you can from any other script with them, but you might also find them useful to avoid writing huge scripts or as an alternative way to add global variables to the game (one that is more forgiving to script updates than quest script variables). A minor variation on the basic principle allows you to also use them for static 'spell' effects.




How to set up an in-game function:
CREATING AN IN-GAME FUNCTION




1) Copy any object that takes a script (I use Gold001). Rename to, e.g., TargFunction.
1) Copy any object that takes a script (e.g. Gold or an Evil Stone). Rename to, e.g., TargFunction.


2) Place a copy somewhere suitable in the world - preferably where you already have something or in your own cell.
2) Place a copy somewhere suitable in the world - preferably where you already have something or in your own cell.


3) Mark the object persistant. Mark it Initially Disabled. Give it a suiable name, e.g. TargFunc01.
3) Mark the object persistent. Give it a suiable name, e.g. TargFunc01.


4) Place a script on the object to do what you want. (See below for a neat example.)
4) Place a script on the object to do your function. Typically this will just consist of the OnActivate block and variables that can be accessed from other scripts. (See example script below.)


5) Call this function by simply doing TargFunc01.Activate player 1.
5) Call this function using the Activate command. (See below.)




Here is an example of a method that you can call to get the position of the target cross hairs:
STATIC FUNCTIONS


If you really want a static function then your best option is to use a remote persistent object - i.e. a true world activator object (e.g. a switch) placed in some hidden location. To call your function:
  [set IGFActRef.someInputVar to someInput]
  IGFActRef.Activate player 1
  [set someOutput IGFActRef.someOutputVar]
LOCAL STATIC FUNCTIONS
This is the same principle but the object is an item (something you can carry) and therefore movable, e.g. a gold coin. The idea is that you move it to the player location so it's GameMode/MenuMode blocks are also active. The item must be a persistant object and (initially) disabled so it is invisible when near the player.
The call syntax is slightly different:
  [set IGFLActRef.someInputVar to someInput]
  set IGFLActRef.enabled to 1
  IGFLActRef.MoveTo player
In this case you are enabling the GameMode/MenuMode block by bringing the object to you. However, you may need to deactivate it sometime later or otherwise make a safety switch to prevent it functioning when you dont expect it to.
You can have the item script do most of the work and instead call the activate method to do the equivalent of a ScriptEffectStart block for spells - the GameMode block being equivalent to the ScriptEffectUpdate block.
  [set IGFActRef.someInputVar to someInput]
  IGFActRef.Activate player 1
  IGFLActRef.MoveTo player
  [set someOutput IGFActRef.someOutputVar]
USEFUL EXAMPLE IGF
Here is an example of a method that you can call to get the position of the target cross hairs and the direction the player is looking:


  scn TargFunctionScript
  scn TargFunctionScript
Line 87: Line 119:




IMPORTANT NOTES
NOTES
 
It turns out there is a bug that can occur if an in-game function is actively processing when the player enters a new cell. The effect is that the item bearing the script suddenly appears in your inventory as if <b>IGFRef.Activate player</b> was called rather than <b>IGFRef.Activate player 1</b>. (EDIT: I later discovered that this was probably due to me mixing up Activate calls for the same object with and without the optional flag. I now always make my calls with the "1" flag to avoid the same bug.)
 
 
If you really want a static function then your best option is to use a remote persistent object - i.e. a true world activator object (e.g. a switch). This has no such issues and has the advantage of accepting slightly neater call syntax:
 
IGFActRef.Activate player
 
(Additionally you do not have to mark the placed IGFRef as initially disabled unless you need it to activate as a sensor for when the player is nearby.)
 
The disadvantage of this is that the GameMode part of the script will never be that useful since the activator item is remote. If you use items, as described above, you can always teleport them to the player location so they trigger every frame. However, in this case you may be better off using an unplayable item (aka token) on the player and using the OnActivate method or switch it on using quest variables.




Another thing to watch for is how many times you call the same IGF activator within a single frame. Like Stage functions, they can 'time-out' if too many calls are made. Additionally, as with (recursive) PlaceAtMe calls, there appears to be a limit of only 4 or 5 activation calls you are allowed to make to the same base object in one frame - possibly due to a general hard-coded recursion call trap that the interpretor makes.(?)
1. Best to always use the '1' flag when you use the Activate command. This prevents any default activation method being triggered, e.g. ending up in your inventory for item IGFs. For static activators this isn't so important but mixing up Activate commands w/ and w/o the '1' flag can lead to 'wierd' effects.


2. Do not try to make too many calls to the same activator in the same frame. 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. (A similar thing happens if you do PlaceAtMe for scripted objects.)


One extra note on Stage functions. Apart from being useful in their own right, they have a very nice goto # / call # functionality.
3. Quest Stage Functions: Apart from being useful in their own right, these have one nice feature that IGFs do not: a call funcion-by-number utility, i.e.


  set x to 10; any value between 0-255
  set x to 10; any value between 0-255
  SetStage MyQuest x
  SetStage MyQuest x


This property can be used to create small linked-lists, stacks, arrays, etc.
This may be used to create small linked-lists, stacks, arrays, random effects, etc.


[[Category: Useful Code]]
[[Category: Useful Code]]

Revision as of 22:47, 11 July 2007

IN-GAME FUNCTIONS by Guidobot


In-game functions are basically scripts on objects (placed in the game) that can be called from any other script. You can also pass variables in and out of that function easily without reference to independent global variables.

In-game functions are easier to create and do not have the restrictions that Stage functions have, e.g. number of lines, reference object calls, variable definiton, etc. You can do almost anything you can from any other script with them, but you might also find them useful to avoid writing huge scripts or as an alternative way to add global variables to the game (one that is more forgiving to script updates than quest script variables). A minor variation on the basic principle allows you to also use them for static 'spell' effects.


CREATING AN IN-GAME FUNCTION


1) Copy any object that takes a script (e.g. Gold or an Evil Stone). Rename to, e.g., TargFunction.

2) Place a copy somewhere suitable in the world - preferably where you already have something or in your own cell.

3) Mark the object persistent. Give it a suiable name, e.g. TargFunc01.

4) Place a script on the object to do your function. Typically this will just consist of the OnActivate block and variables that can be accessed from other scripts. (See example script below.)

5) Call this function using the Activate command. (See below.)


STATIC FUNCTIONS


If you really want a static function then your best option is to use a remote persistent object - i.e. a true world activator object (e.g. a switch) placed in some hidden location. To call your function:

 [set IGFActRef.someInputVar to someInput]
 IGFActRef.Activate player 1
 [set someOutput IGFActRef.someOutputVar]


LOCAL STATIC FUNCTIONS


This is the same principle but the object is an item (something you can carry) and therefore movable, e.g. a gold coin. The idea is that you move it to the player location so it's GameMode/MenuMode blocks are also active. The item must be a persistant object and (initially) disabled so it is invisible when near the player.

The call syntax is slightly different:

 [set IGFLActRef.someInputVar to someInput]
 set IGFLActRef.enabled to 1
 IGFLActRef.MoveTo player

In this case you are enabling the GameMode/MenuMode block by bringing the object to you. However, you may need to deactivate it sometime later or otherwise make a safety switch to prevent it functioning when you dont expect it to.

You can have the item script do most of the work and instead call the activate method to do the equivalent of a ScriptEffectStart block for spells - the GameMode block being equivalent to the ScriptEffectUpdate block.

 [set IGFActRef.someInputVar to someInput]
 IGFActRef.Activate player 1
 IGFLActRef.MoveTo player
 [set someOutput IGFActRef.someOutputVar]


USEFUL EXAMPLE IGF


Here is an example of a method that you can call to get the position of the target cross hairs and the direction the player is looking:

scn TargFunctionScript

; initial position vector
float xPos
float yPos
float zPos

; fly vector
float dx
float dy
float dz

; private
float ang
float x
float x2
float sin
float cos

Begin OnActivate

; horizontal fly vector
set ang to player.GetAngle z
if ang > 180
  set ang to (ang)-360
endif
set x to ang*0.0174532925
set x2 to x*x
set sin to x*(1-(x2/6)*(1-(x2/20)*(1-(x2/42)*(1-(x2/72)*(1-x2/110)))))
set cos to 1-0.5*x2*(1-(x2/12)*(1-(x2/30)*(1-(x2/56)*(1-x2/90))))
set dx to 10*sin
set dy to 10*cos

; vertical fly vector
set ang to player.GetAngle x
set x to -ang*0.0174532925
set x2 to x*x
set sin to x*(1-(x2/6)*(1-(x2/20)*(1-(x2/42)*(1-(x2/72)*(1-x2/110)))))
set cos to 1-0.5*x2*(1-(x2/12)*(1-(x2/30)*(1-(x2/56)*(1-x2/90))))
set dz to 10*sin

; initial position vector (to add to player coords)
set xPos to 5*dx*cos
set yPos to 5*dy*cos
set zPos to 118-25*(player.IsSneaking)+5*dz

End

To use this function:

; some script
;...
TargFunc01.Activate player 1
set xPos to (TargFunc01.xPos)+(player.GetPos x)
set yPos to (TargFunc01.yPos)+(player.GetPos y)
set zPos to (TargFunc01.zPos)+(player.GetPos z)

set dx to TargFunc01.dx
set dy to TargFunc01.dy
set dz to TargFunc01.dz


NOTES


1. Best to always use the '1' flag when you use the Activate command. This prevents any default activation method being triggered, e.g. ending up in your inventory for item IGFs. For static activators this isn't so important but mixing up Activate commands w/ and w/o the '1' flag can lead to 'wierd' effects.

2. Do not try to make too many calls to the same activator in the same frame. 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. (A similar thing happens if you do PlaceAtMe for scripted objects.)

3. Quest Stage Functions: Apart from being useful in their own right, these have one nice feature that IGFs do not: a call funcion-by-number utility, i.e.

set x to 10; any value between 0-255
SetStage MyQuest x

This may be used to create small linked-lists, stacks, arrays, random effects, etc.