Difference between revisions of "Simulating new functions"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>JustTim
(corrected my horrible math mistakes ^^)
imported>JustTim
(Changed external URL because of website domain change.)
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Deprecated Article|This article is obsolete since [[OBSE]] has support for [[User Functions]].}}
=== Introduction ===
Writing complex scripts for oblivion can be very painful and frustrating. Not being able to write reusable functions that execute directly on call instead of the next frame is one of the major problems (at least for me).
Writing complex scripts for oblivion can be very painful and frustrating. Not being able to write reusable functions that execute directly on call instead of the next frame is one of the major problems (at least for me).


Line 4: Line 8:
When you call setStage in a script, the related stage result script will be executed immediately BEFORE the current script continues! This is therefore a great way to write immediately executing function calls!
When you call setStage in a script, the related stage result script will be executed immediately BEFORE the current script continues! This is therefore a great way to write immediately executing function calls!


I've spent MANY hours to advance this idea to a fully reusable function framework that can easily be used in your scripts. Here is what i came up with:
I've spent MANY hours to advance this idea to a fully reusable function framework that can easily be used in your scripts.


=== The easy way: Math Library ESM ===
The easiest way to use stage functions is by using [http://www.hazardx.com/details.php?file=68 this ESM Math Library]. It already contains all math functions listed in the [[stage_function_repository|Stage Function Repository]]. To use it copy the ESM file to your oblivion data folder and select it as an additional master file when loading your mod with the Construction Set. By doing this all the necessary setup steps are already done for you. All you need to do to use a function is to call it. You can also add new stages to the predefined function quest very easily in your mod without all the setup hassle.
Be aware that other users of your mod will need the Library too to run it.


Create a Quest just called "f" (for "function"), ACTIVATE "ALLOW REPEATED STAGES" and attach the following quest script:
Download: [http://www.hazardx.com/details.php?file=68 ESM Math Library v1.0].
 
=== Do it yourself: Setup ===
 
* Open any Plugin you wish or create a new one with the Construction Set
* Create a new Quest called "f" (yes, just the letter "f", nothing more)
* Activate the Checkbox "Allow repeated stages". (This is VERY important!!)
* Create a new Quest Script and copy the whole FunctionQuestScript from this article into this script. Don't forget to attach it to your f-Quest!
<pre>ScriptName FunctionQuestScript
<pre>ScriptName FunctionQuestScript


Line 48: Line 62:
   endif
   endif
End</pre>
End</pre>
This is a generalized function framework that can be re-used for as many functions as you like.


And now make stage 10 for this quest with the following code:
* Now create stage 10 for this quest with the following code:
<pre>;FUNCTION float Arctan(float tan)
<pre>;FUNCTION float Arctan(float tan)
;Approximation by Taylor Series - script by DragoonWraith
;Approximation by Taylor Series - script by DragoonWraith
Line 60: Line 73:
set f.fout to (f.fin1 - (f.t3/3) + (f.t5/5) - (f.t7/7))</pre>
set f.fout to (f.fin1 - (f.t3/3) + (f.t5/5) - (f.t7/7))</pre>


And stage 20:
* And stage 20:
<pre>;FUNCTION float getAngle(float x, float y)
<pre>;FUNCTION float getAngle(float x, float y)


Line 82: Line 95:
;CALL float Arctan(float tan)
;CALL float Arctan(float tan)
set f.fin1 to f.tan
set f.fin1 to f.tan
setStage f 24
setStage f 10


if f.fout > (f.pi/2)
if f.fout > (f.pi/2)
Line 91: Line 104:


set f.fout to ((f.fout*f.rad) + f.ang)</pre>
set f.fout to ((f.fout*f.rad) + f.ang)</pre>
* Okay, the function setup is complete.


Okay, the function setup is complete. Now you've already got 2 functions: One to calculate the arctan and another one that uses arctan to calculate the angle of a vector. To get the angle between two objects in a script just type:
=== Usage ===
 
Now you've already got 2 functions: One to calculate the arctan and another one that uses arctan to calculate the angle of a vector. To get the angle between two objects in a script just type:
<pre>;CALL float getAngle(float x, float y)
<pre>;CALL float getAngle(float x, float y)
set f.fin1 to ( Object2.getPos x - Object1.getPos x )
set f.fin1 to ( Object2.getPos x - Object1.getPos x )
Line 98: Line 114:
setStage f 20
setStage f 20
set ResultingAngleZ to f.fout</pre>
set ResultingAngleZ to f.fout</pre>
Et voilà, here is your Z-Angle between Object 1 and 2! You can reuse the function wherever you like, how often you wish to and you can even call functions from inside another stage of "f" (aka. another function)!
Et voilà, here is your Z-Angle between Object 1 and 2!


I is also very easy to share the functions with others since you only need to share the code of the stage result script for your function.
=== Conclusion ===
 
You can reuse the function wherever you like, how often you wish to and you can even call functions from inside another stage of "f" (aka. another function)!
 
It is also very easy to share the functions with others since you only need to share the code of the stage result script for your function.


The only downsides are that you have to define all vars in the quest script (it compiles when you define them in the stage result script, but they'll always be 0) and the limited maximum length of each quest result script (which isn't a big problem since you are able to split a single function into multiple stages).
The only downsides are that you have to define all vars in the quest script (it compiles when you define them in the stage result script, but they'll always be 0) and the limited maximum length of each quest result script (which isn't a big problem since you are able to split a single function into multiple stages).
Line 107: Line 127:
The new version of the getAngle Function seems to be very accurate, but if anyone has an idea on how to improve these scripts for accuracy and performance then please contribute!
The new version of the getAngle Function seems to be very accurate, but if anyone has an idea on how to improve these scripts for accuracy and performance then please contribute!


[[Category:Useful Code]]
=== Function Repository ===
 
If you are looking for a complete setup with many math functions included then take a look at the [[stage_function_repository|Stage Function Repository]]!
 
[[Category:Solutions]]
[[Category:Solutions]]

Latest revision as of 13:12, 17 April 2013


Introduction[edit | edit source]

Writing complex scripts for oblivion can be very painful and frustrating. Not being able to write reusable functions that execute directly on call instead of the next frame is one of the major problems (at least for me).

But Kkuhlmann from Bethesda had a great idea to make a workaround: Quest Stages! When you call setStage in a script, the related stage result script will be executed immediately BEFORE the current script continues! This is therefore a great way to write immediately executing function calls!

I've spent MANY hours to advance this idea to a fully reusable function framework that can easily be used in your scripts.

The easy way: Math Library ESM[edit | edit source]

The easiest way to use stage functions is by using this ESM Math Library. It already contains all math functions listed in the Stage Function Repository. To use it copy the ESM file to your oblivion data folder and select it as an additional master file when loading your mod with the Construction Set. By doing this all the necessary setup steps are already done for you. All you need to do to use a function is to call it. You can also add new stages to the predefined function quest very easily in your mod without all the setup hassle. Be aware that other users of your mod will need the Library too to run it.

Download: ESM Math Library v1.0.

Do it yourself: Setup[edit | edit source]

  • Open any Plugin you wish or create a new one with the Construction Set
  • Create a new Quest called "f" (yes, just the letter "f", nothing more)
  • Activate the Checkbox "Allow repeated stages". (This is VERY important!!)
  • Create a new Quest Script and copy the whole FunctionQuestScript from this article into this script. Don't forget to attach it to your f-Quest!
ScriptName FunctionQuestScript

; Internals
short doOnce
float fQuestDelayTime

; Constants
float pi
float rad


; Function In- and Output
float fin1
float fin2
float fin3
float fout
float fout2
float fout3


;S10 FUNCTION Arctan
float t3
float t5
float t7

;S20 FUNCTION getAngle
float tan
float ang


; Set constants first
Begin Gamemode
  if doOnce == 0
    set pi to 3.1415927
    set rad to 180.0/pi

    set fQuestDelayTime to 30
    set doOnce to 1
  endif
End
  • Now create stage 10 for this quest with the following code:
;FUNCTION float Arctan(float tan)
;Approximation by Taylor Series - script by DragoonWraith

set f.t3 to (f.fin1 * f.fin1 * f.fin1)
set f.t5 to (f.t3 * f.fin1 * f.fin1)
set f.t7 to (f.t5 * f.fin1 * f.fin1)

set f.fout to (f.fin1 - (f.t3/3) + (f.t5/5) - (f.t7/7))
  • And stage 20:
;FUNCTION float getAngle(float x, float y)

set f.tan to (f.fin1/f.fin2)

if f.tan >1 || f.tan < -1
  set f.tan to (f.fin2/ -f.fin1)
  if f.fin1 >= 0
    set f.ang to 90
  else
    set f.ang to -90
  endif
else
  if f.fin2 >= 0
    set f.ang to 0
  else
    set f.ang to 180
  endif
endif

;CALL float Arctan(float tan)
set f.fin1 to f.tan
setStage f 10

if f.fout > (f.pi/2)
  set f.fout to (f.pi/2)
elseif f.fout < (f.pi/ -2)
  set f.fout to (f.pi/ -2)
endif

set f.fout to ((f.fout*f.rad) + f.ang)
  • Okay, the function setup is complete.

Usage[edit | edit source]

Now you've already got 2 functions: One to calculate the arctan and another one that uses arctan to calculate the angle of a vector. To get the angle between two objects in a script just type:

;CALL float getAngle(float x, float y)
set f.fin1 to ( Object2.getPos x - Object1.getPos x )
set f.fin2 to ( Object2.getPos y - Object1.getPos y )
setStage f 20
set ResultingAngleZ to f.fout

Et voilà, here is your Z-Angle between Object 1 and 2!

Conclusion[edit | edit source]

You can reuse the function wherever you like, how often you wish to and you can even call functions from inside another stage of "f" (aka. another function)!

It is also very easy to share the functions with others since you only need to share the code of the stage result script for your function.

The only downsides are that you have to define all vars in the quest script (it compiles when you define them in the stage result script, but they'll always be 0) and the limited maximum length of each quest result script (which isn't a big problem since you are able to split a single function into multiple stages).

Many thanks go tu Kkuhlmann for his great idea, to DragoonWraith for the Arctan function and to Maian for telling me that my old functions were completely wrong. :) The new version of the getAngle Function seems to be very accurate, but if anyone has an idea on how to improve these scripts for accuracy and performance then please contribute!

Function Repository[edit | edit source]

If you are looking for a complete setup with many math functions included then take a look at the Stage Function Repository!