Difference between revisions of "Talk:Simulating new functions"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>JustTim
imported>Maian
Line 191: Line 191:


BTW: If there is something you'd like to change or contribute to the article or if you know of a good way to write a simplier example don't hesitate to modify the article directly. I know the article lacks a professional writing style (presumably due to me not being a native english-speaker) and it would be cool if someone could help me to bring this into a professional, more wiki-like (and error-free) form. --[[User:JustTim|JustTim]] 15:16, 8 May 2006 (EDT)
BTW: If there is something you'd like to change or contribute to the article or if you know of a good way to write a simplier example don't hesitate to modify the article directly. I know the article lacks a professional writing style (presumably due to me not being a native english-speaker) and it would be cool if someone could help me to bring this into a professional, more wiki-like (and error-free) form. --[[User:JustTim|JustTim]] 15:16, 8 May 2006 (EDT)
This is a script I made but ended up never using once I discovered the getHeadingAngle function (so it's rather untested and probably has bugs). It's basically a lookup table, one row for a degree (so the script is large), except since there are no arrays, I made the look up act as a binary search. It also doesn't use the quest result script thing - I'm using the method I described above.
<pre>scn ArcTanScript
; by Maian
float x
float y
float result
float ratio
begin GameMode
if x == 0
if y >= 0
set result to 90
else
set result to 270
endif
return
endif
set ratio to y / x
if ratio < 0
set ratio to -ratio
endif
if ratio < 1.018
if ratio < 0.414
if ratio < 0.203
if ratio < 0.096
if ratio < 0.044
if ratio < 0.009
set result to 0
elseif ratio < 0.026
set result to 1
else
set result to 2
endif
else ; 0.044
if ratio < 0.061
set result to 3
elseif ratio < 0.079
set result to 4
else
set result to 5
endif
endif
else ; 0.096
if ratio < 0.149
if ratio < 0.114
set result to 6
elseif ratio < 0.132
set result to 7
else
set result to 8
endif
else ; 0.149
if ratio < 0.167
set result to 9
elseif ratio < 0.185
set result to 10
else
set result to 11
endif
endif
endif
else ; 0.203
if ratio < 0.296
if ratio < 0.24
if ratio < 0.222
set result to 12
else
set result to 13
endif
else ; 0.24
if ratio < 0.259
set result to 14
elseif ratio < 0.277
set result to 15
else
set result to 16
endif
endif
else ; 0.296
if ratio < 0.354
if ratio < 0.315
set result to 17
elseif ratio < 0.335
set result to 18
else
set result to 19
endif
else ; 0.354
if ratio < 0.374
set result to 20
elseif ratio < 0.394
set result to 21
else
set result to 22
endif
endif
endif
endif
else ; 0.414
if ratio < 0.662
if ratio < 0.521
if ratio < 0.456
if ratio < 0.435
set result to 23
else
set result to 24
endif
else ; 0.456
if ratio < 0.477
set result to 25
elseif ratio < 0.499
set result to 26
else
set result to 27
endif
endif
else ; 0.521
if ratio < 0.589
if ratio < 0.543
set result to 28
elseif ratio < 0.566
set result to 29
else
set result to 30
endif
else ; 0.589
if ratio < 0.613
set result to 31
elseif ratio < 0.637
set result to 32
else
set result to 33
endif
endif
endif
else ; 0.662
if ratio < 0.824
if ratio < 0.74
if ratio < 0.687
set result to 34
elseif ratio < 0.713
set result to 35
else
set result to 36
endif
else ; 0.74
if ratio < 0.767
set result to 37
elseif ratio < 0.795
set result to 38
else
set result to 39
endif
endif
else ; 0.824
if ratio < 0.916
if ratio < 0.854
set result to 40
elseif ratio < 0.885
set result to 41
else
set result to 42
endif
else ; 0.916
if ratio < 0.949
set result to 43
elseif ratio < 0.983
set result to 44
else
set result to 45
endif
endif
endif
endif
endif
else ; 1.018
if ratio < 2.414
if ratio < 1.511
if ratio < 1.213
if ratio < 1.091
if ratio < 1.054
set result to 46
else
set result to 47
endif
else ; 1.091
if ratio < 1.13
set result to 48
elseif ratio < 1.171
set result to 49
else
set result to 50
endif
endif
else ; 1.213
if ratio < 1.351
if ratio < 1.257
set result to 51
elseif ratio < 1.303
set result to 52
else
set result to 53
endif
else ; 1.351
if ratio < 1.402
set result to 54
elseif ratio < 1.455
set result to 55
else
set result to 56
endif
endif
endif
else ; 1.511
if ratio < 1.842
if ratio < 1.632
if ratio < 1.57
set result to 57
else
set result to 58
endif
else ; 1.632
if ratio < 1.698
set result to 59
elseif ratio < 1.767
set result to 60
else
set result to 61
endif
endif
else ; 1.842
if ratio < 2.097
if ratio < 1.921
set result to 62
elseif ratio < 2.006
set result to 63
else
set result to 64
endif
else ; 2.097
if ratio < 2.194
set result to 65
elseif ratio < 2.3
set result to 66
else
set result to 67
endif
endif
endif
endif
else ; 2.414
if ratio < 4.915
if ratio < 3.172
if ratio < 2.675
if ratio < 2.539
set result to 68
elseif ratio < 2.006
set result to 69
endif
else ; 2.675
if ratio < 2.824
set result to 70
elseif ratio < 2.989
set result to 71
else
set result to 72
endif
endif
else ; 3.172
if ratio < 3.867
if ratio < 3.376
set result to 73
elseif ratio < 3.606
set result to 74
else
set result to 75
endif
else ; 3.867
if ratio < 4.165
set result to 76
elseif ratio < 4.511
set result to 77
else
set result to 78
endif
endif
endif
else ; 4.915
if ratio < 10.385
if ratio < 6.691
if ratio < 5.396
set result to 79
elseif ratio < 5.976
set result to 80
else
set result to 81
endif
else ; 6.691
if ratio < 7.596
set result to 82
elseif ratio < 8.777
set result to 83
else
set result to 84
endif
endif
else ; 10.385
if ratio < 22.904
if ratio < 10.385
set result to 85
elseif ratio < 12.706
set result to 86
else
set result to 87
endif
else ; 22.904
if ratio < 38.188
set result to 88
elseif ratio < 114.589
set result to 89
else
set result to 90
endif
endif
endif
endif
endif
endif
if x < 0 && y < 0
set result to result + 180
elseif x < 0
set result to -result + 180
elseif y < 0
set result to -result + 360
else
set result to result
endif
end</pre>
--[[User:Maian|Maian]] 16:50, 8 May 2006 (EDT)

Revision as of 15:50, 8 May 2006

I've tried creating a custom "function" that can be called by other scripts. The basic approach I took was to make the function a quest script, and have the calling script call the function via |StartQuest function_quest|. Ex:

I have a quest called testfunc that is initially disabled and contains the following script:

scn testfuncscript

float param1
float param2
float result

begin GameMode
   Message "start func", 1
   set result to param1 + param2
   Message "end func: %.0f", result, 1
   StopQuest testfunc
end

In another script, I call this "function":

scn testscript

float r

begin OnActivate
   Message "before call", 1
   set testfunc.param1 to 10
   set testfunc.param2 to 20
   StartQuest testfunc
   set r to testfunc.result
   Message "after call: %.0f", r, 1
end

However, the above code doesn't work. The order of the output illustrates why:

before call
after call: 0
start func
end func: 30

This is what it should be:

before call
start func
end func: 30
after call: 30

The problem is that the calling script doesn't wait for the function script to execute, and instead the function script is delayed until after the calling script finishes executing.

So is there any way that can bypass this problem without resorting to nasty "wait for the other script to finish" hacks? (I could make the calling script have a GameMode block that would repeatly check when the function finishes executing, but that would be a serious PITA.) I suspect this same problem would've arisen if I had tried creating a function script by attaching it to a persistent object instead of a quest (and calling it via the Activate function).

--Maian 03:59, 18 April 2006 (EDT)


I'm just kind of brainstorming here, but you might try making a quest, marked "Allow repeated stages" so you can call the stages repeatedly, and make (say) stage 10 be your "function". Quest stage results are executed immediately, while the current script is processing, so you wouldn't have to wait for the results.

Keep your variables in your quest script. In stage 10 results, you'd have:

   Message "start func", 1
   set testfunc.result to testfunc.param1 + testfunc.param2
   Message "end func: %.0f", testfunc.result, 1

To call this function, you'd do the following:


scn testscript

float r

begin OnActivate
   Message "before call", 1
   set testfunc.param1 to 10
   set testfunc.param2 to 20
   setstage testfunc 10    ; call the "function"
   set r to testfunc.result
   Message "after call: %.0f", r, 1
end

I think this should work (I haven't tried it).

--Kkuhlmann 14:02, 18 April 2006 (EDT)

I've been doing this for awhile now with OnActivate functions placed on activators. The reference you use to activate it acts as a parameter to tell it how to act. Then when that function is done it activates the calling object to let it know that it is finished and it is time to process the results.

So for instance

scn ActivateFunction
ref incoming

begin OnActivate
  set incoming to GetActionRef
  if (incoming == CallingScriptRef.Me)
     set CallingScriptRef.Value to CallingScriptRef.Value + 3
     CallingScriptRef.Activate CallingScriptRef.ActivateFunctionRef 1
     return
  endif
end
scn CallingScript
ref Me
ref ActivateFunctionRef
long Value
ref incoming

begin OnLoad
  set Me to GetSelf
  set Value to 0
  Message "I am storing a value of %.0f", Value, 1
end

begin OnActivate
  set incoming to GetActionRef
  if (incoming == ActivateFunctionRef)
    Message "Now I am storing a value of %.0f", Value, 1
    return
  endif
  ActivateFunctionRef.Activate Me 1
end

This removes the need for a game mode block and allows function passing (or setting in a persistent reference). I've used this quite successfully for some cool stuff I'm finishing the testing on. --Tegid 14:44, 18 April 2006 (EDT)

After some experimentation, I've verified that making the function script an object script and attaching it to a dummy object (in activator called testfunc in my case), it works. That is, it satisfies the following conditions:

  1. It can be called (via |testfunc.Activate player, 1|).
  2. The function is executed immediately rather than after the script that called it.
  3. It can be called even in places where the dummy object isn't at, e.g. I placed the dummy object inside an interior cell and called it in an exterior cell. This was what I was most worried about with this approach - that the function would only work if the dummy object is in the same area. I haven't tested this extensively, so it may be the case that it works only because the dummy object is still in memory, but I suspect that's not the case.

Tegid, in your example, the called function apparently needs a reference to the script calling it, which defeats the purpose of making the function generic (after all, the main reason for creating a new function is to share code between 2+ functions). Maybe if your script just checked if incoming.Me was set and just used incoming rather than CallingScriptRef, it could work generically.

Kkuhlmann, I haven't tried your method yet, but I'm post an update once I do so.

Thanks for all the help! --Maian 21:49, 18 April 2006 (EDT)

Kkuhlmann's solution also worked.

For reference, here's my dummy object + activate script solution:

On a dummy object:

scn testfuncobjscript

float param1
float param2
float result

begin OnActivate
   if IsActionRef Player != 1
      Message "start func", 1
      set result to param1 + param2
      Message "end func: %.0f", result, 1
   else
      Activate
   endif
end

Calling script:

scn testobjscript

float r
ref self

begin Onload
   set self to GetSelf
end

begin OnActivate
   Message "before call", 1
   set testfuncref.param1 to 10
   set testfuncref.param2 to 20
   testfuncref.Activate self, 1
   set r to testfuncref.result
   Message "after call: %.0f", r, 1
end

--Maian 01:47, 19 April 2006 (EDT)

The CallingScriptRef is just your single point of entry into the set of scripted functions. It is a persistent reference Activator like your testfuncref. Also, it has not been my experience that Activate calls interrupt the flow of script parsing. I was under the impression that the Activate call really just sets a bit so that when that script is reached, the OnActivate block is executed. --Tegid 11:07, 19 April 2006 (EDT)


I love the solution kkuhlmann has written! This is by far the best idea for immediately executing function calls! I've advanced his idea to a working solution! See the article for more info. --JustTim 11:26, 7 May 2006 (EDT)

The math for getAngle is definitely not correct. You mixed up cos and sin (cos = x/h; sin = y/h). I'm not sure why you're multiplying cos or sin with 180/PI since that's not the angle. In fact, you shouldn't even be using cos or sin when trying to get the arctangent. --Maian 00:56, 8 May 2006 (EDT)

Oops, now i see why i've recieved some strange results. But the results aren't too far from what they should be. ^^ But i'd appreciate a corrected version very much. As said before my math skills are VERY limited and those functions are nothing but patchwork of stuff i found on the net, put together by trial and error instead of reasonable mathematics. :) --JustTim 11:34, 8 May 2006 (EDT)

BTW: If there is something you'd like to change or contribute to the article or if you know of a good way to write a simplier example don't hesitate to modify the article directly. I know the article lacks a professional writing style (presumably due to me not being a native english-speaker) and it would be cool if someone could help me to bring this into a professional, more wiki-like (and error-free) form. --JustTim 15:16, 8 May 2006 (EDT)

This is a script I made but ended up never using once I discovered the getHeadingAngle function (so it's rather untested and probably has bugs). It's basically a lookup table, one row for a degree (so the script is large), except since there are no arrays, I made the look up act as a binary search. It also doesn't use the quest result script thing - I'm using the method I described above.

scn ArcTanScript
; by Maian

float x
float y
float result
float ratio

begin GameMode
	if x == 0
		if y >= 0
			set result to 90
		else
			set result to 270
		endif
		return
	endif
	set ratio to y / x
	if ratio < 0
		set ratio to -ratio
	endif
	if ratio < 1.018
		if ratio < 0.414
			if ratio < 0.203
				if ratio < 0.096
					if ratio < 0.044
						if ratio < 0.009
							set result to 0
						elseif ratio < 0.026
							set result to 1
						else
							set result to 2
						endif
					else	; 0.044
						if ratio < 0.061
							set result to 3
						elseif ratio < 0.079
							set result to 4
						else
							set result to 5
						endif
					endif
				else	; 0.096
					if ratio < 0.149
						if ratio < 0.114
							set result to 6
						elseif ratio < 0.132
							set result to 7
						else
							set result to 8
						endif
					else	; 0.149
						if ratio < 0.167
							set result to 9
						elseif ratio < 0.185
							set result to 10
						else
							set result to 11
						endif
					endif
				endif
			else	; 0.203
				if ratio < 0.296
					if ratio < 0.24
						if ratio < 0.222
							set result to 12
						else
							set result to 13
						endif
					else	; 0.24
						if ratio < 0.259
							set result to 14
						elseif ratio < 0.277
							set result to 15
						else
							set result to 16
						endif
					endif
				else	; 0.296
					if ratio < 0.354
						if ratio < 0.315
							set result to 17
						elseif ratio < 0.335
							set result to 18
						else
							set result to 19
						endif
					else	; 0.354
						if ratio < 0.374
							set result to 20
						elseif ratio < 0.394
							set result to 21
						else
							set result to 22
						endif
					endif
				endif
			endif
		else	; 0.414
			if ratio < 0.662
				if ratio < 0.521
					if ratio < 0.456
						if ratio < 0.435
							set result to 23
						else
							set result to 24
						endif
					else	; 0.456
						if ratio < 0.477
							set result to 25
						elseif ratio < 0.499
							set result to 26
						else
							set result to 27
						endif
					endif
				else	; 0.521
					if ratio < 0.589
						if ratio < 0.543
							set result to 28
						elseif ratio < 0.566
							set result to 29
						else
							set result to 30
						endif
					else	; 0.589
						if ratio < 0.613
							set result to 31
						elseif ratio < 0.637
							set result to 32
						else
							set result to 33
						endif
					endif
				endif
			else	; 0.662
				if ratio < 	0.824
					if ratio < 0.74
						if ratio < 0.687
							set result to 34
						elseif ratio < 0.713
							set result to 35
						else
							set result to 36
						endif
					else	; 0.74
						if ratio < 0.767
							set result to 37
						elseif ratio < 0.795
							set result to 38
						else
							set result to 39
						endif
					endif
				else	; 0.824
					if ratio < 0.916
						if ratio < 0.854
							set result to 40
						elseif ratio < 0.885
							set result to 41
						else
							set result to 42
						endif
					else	; 0.916
						if ratio < 0.949
							set result to 43
						elseif ratio < 0.983
							set result to 44
						else
							set result to 45
						endif
					endif
				endif
			endif
		endif
	else	; 1.018
		if ratio < 2.414
			if ratio < 1.511
				if ratio < 1.213
					if ratio < 1.091
						if ratio < 1.054
							set result to 46
						else
							set result to 47
						endif
					else	; 1.091
						if ratio < 1.13
							set result to 48
						elseif ratio < 1.171
							set result to 49
						else
							set result to 50
						endif
					endif
				else	; 1.213
					if ratio < 1.351
						if ratio < 1.257
							set result to 51
						elseif ratio < 1.303
							set result to 52
						else
							set result to 53
						endif
					else	; 1.351
						if ratio < 1.402
							set result to 54
						elseif ratio < 1.455
							set result to 55
						else
							set result to 56
						endif
					endif
				endif
			else	; 1.511
				if ratio < 	1.842
					if ratio < 1.632
						if ratio < 1.57
							set result to 57
						else
							set result to 58
						endif
					else	; 1.632
						if ratio < 1.698
							set result to 59
						elseif ratio < 1.767
							set result to 60
						else
							set result to 61
						endif
					endif
				else	; 1.842
					if ratio < 2.097
						if ratio < 1.921
							set result to 62
						elseif ratio < 2.006
							set result to 63
						else
							set result to 64
						endif
					else	; 2.097
						if ratio < 2.194
							set result to 65
						elseif ratio < 2.3
							set result to 66
						else
							set result to 67
						endif
					endif
				endif
			endif
		else	; 2.414
			if ratio < 4.915
				if ratio < 3.172
					if ratio < 2.675
						if ratio < 2.539
							set result to 68
						elseif ratio < 2.006
							set result to 69
						endif
					else	; 2.675
						if ratio < 2.824
							set result to 70
						elseif ratio < 2.989
							set result to 71
						else
							set result to 72
						endif
					endif
				else	; 3.172
					if ratio < 3.867
						if ratio < 3.376
							set result to 73
						elseif ratio < 3.606
							set result to 74
						else
							set result to 75
						endif
					else	; 3.867
						if ratio < 4.165
							set result to 76
						elseif ratio < 4.511
							set result to 77
						else
							set result to 78
						endif
					endif
				endif
			else	; 4.915
				if ratio < 	10.385
					if ratio < 6.691
						if ratio < 5.396
							set result to 79
						elseif ratio < 5.976
							set result to 80
						else
							set result to 81
						endif
					else	; 6.691
						if ratio < 7.596
							set result to 82
						elseif ratio < 8.777
							set result to 83
						else
							set result to 84
						endif
					endif
				else	; 10.385
					if ratio < 22.904
						if ratio < 10.385
							set result to 85
						elseif ratio < 12.706
							set result to 86
						else
							set result to 87
						endif
					else	; 22.904
						if ratio < 38.188
							set result to 88
						elseif ratio < 114.589
							set result to 89
						else
							set result to 90
						endif
					endif
				endif
			endif
		endif
	endif
	if x < 0 && y < 0
		set result to result + 180
	elseif x < 0
		set result to -result + 180
	elseif y < 0
		set result to -result + 360
	else
		set result to result
	endif
end

--Maian 16:50, 8 May 2006 (EDT)