PDA

View Full Version : Advanced Question: RTBN Calls from Inside an Interaction


jase439
10th Jul 2005, 9:56 PM
Does anyone know what magic incantation is required to make an RTBN call from inside the execution tree of an interaction? Is it even possible? All my RTBN calls seem to fail and return FALSE in this context, even if op6=0x02 (push onto my stack) is specified. The same call, when invoked outside of an interaction, works fine.

jase439
11th Jul 2005, 5:03 PM
On some off chance someone else reads this thread, I discovered that setting op2=0x06 did the trick. I had previously tried setting these bit flags to 0x02 without success, so I'm guessing its bit 2 in this field that does whatever magic I needed.

mod_bv
11th Jul 2005, 5:25 PM
Wow! Nice find!

Inge Jones
11th Jul 2005, 7:43 PM
What's RTBN?

J. M. Pescado
12th Jul 2005, 12:11 AM
Run Tree By Name. The op2 bits determine a few factors like whether or not you're running it from the global list, the semiglobal list, or the local list strings, and how the arguments are passed. If you set bit 0x01, it should run from the big global list. If you set 0x02, it'll run from the semiglobal STR 0x12Fs, and if you set 0x04, it'll run from the local STRs. If you set 0x10, it'll pass the arguments from the code line, if you set 0x20, it'll pass (I think) from the params. Otherwise, if you set none of these, it'll pass the temp values as your arguments.

jase439
12th Jul 2005, 4:41 AM
The thing that has me perplexed was that the RTBN call was made from a semi-global and the call tree prim string was in the semi-global's STR# 0x12F. I had previously tried passing 0x02 in the flags op to indicate that that lookup should proceed using the semi-globals, but came up empty-handed. Then I happened to notice some code down in the ShoppingRackGlobals that was structured similarly by making a similar RTBN call, however it was passing 0x06 to op2. The significance of needing to have both bits 1 and 2 here is not entirely clear to me, but it worked.

Anyway, the long and short of it: I am not convinced it had anything to do with the fact that I was making the call from an interaction per se. The calling context may have been slightly different and therefore required the extra flag bits to resolve the tree name properly. Semi-globals always manage to get me turned around on my head when it comes to STR# resolution of any kind.

J

Inge Jones
12th Jul 2005, 8:03 AM
Thanks Pescado

jase439
12th Jul 2005, 7:42 PM
For the curious (or not)...I went back last night and tried passing 0x06 to op2 on another RTBN call that was failing for me previously from another semi-global interaction, and it worked. Six is my lucky number :)

mod_bv
13th Jul 2005, 2:54 AM
So op2=0x06 works to make an RTBN call?

I noticed a weird pattern in your finds. op6=0x02 proves false and ends the BHAV. But op2=0x06. Is all this info correct?

jase439
13th Jul 2005, 5:42 AM
op6 just specifies how you want to call the tree:

0x00 and 0x02 are similiar in that the called behavior runs in the context of the active stack object. The main difference is that op6=0x00 will treat the absence of the "named" function as an expected condition and just returns false whereas 0x02 treats the call as though you were calling a known private function. If it doesn't exist you get an Undefined Transition or Missing Check Tree (I can't recall the specific text) or some such thing.

op2 on the other hand, as JM describes, tells RTBN how to resolve the name of the function you're trying to call and how the params are to be passed to the callee. op2 is the operand of interest here, and op2=0x06 is the lucky set of bits needed to make this call. The value of op6 is tangential to this discussion.

J

PS. op6=0x01 is rarely used (but I tried it once for shitz n giggles) and means "run in My's stack"...it basically acts like Push Interaction and you can use it to "jump contexts" - effectively changing the "My" object to something else. The call is asynchronous, so you can't sit and wait for a return value from this call. It basically just queues up a function call on the stack object to be run later when that the stack objects main loop gets processed. The one caveat here is that a false return when op6=0x01 does NOT mean failure. I think a false return means the action could not be run immediately or something and was queued (possibly an indicator about the stack object's current idle state?) - but I'm not entirely certain. All I know is that true and false are both normal when op6 is 0x01.

Sorry if that is clear as mud.

mod_bv
13th Jul 2005, 5:45 PM
Thanks, jase!

But why do you need to know about making an RTBN call from inside the execution tree of an interaction? Is it just for knowledge purposes, or is it a clue to a new feature in the InTeenimater :hint, hint:?

Inge Jones
21st Oct 2005, 12:56 PM
Is it not possible to specify which object type holds the code you want to run, to avoid any possibility of having a duplicate BHAV name game-wide?

dizzy2
22nd Oct 2005, 9:00 AM
It looks to me like operand 6 is the mode of the RTBN (0 = push onto Stack Object's stack, 1 = run in my stack, 2 = run in Stack Object's stack). So, either the Stack Object or Me is the ID of the object whose named BHAV you want to perform.

Operand 2 is the flags (bit 0 = global STR#, bit 1 = semi-global STR#, bit 4 = specify params, bit 5 = use current params).

If bit 0 and 1 are clear, then the STR# is private.

Bit 3 seems to relate to the Idle system (clear = idle, set = non-idle), but I have no idea what it does.

EDIT: Okay, I think that's sorted it. :P (Fixing disaSim2...)

Inge Jones
22nd Oct 2005, 9:16 AM
I know you can specify exactly where to get the string from, but it seems having got the BHAV name from the string, there is no further way of saying which object to start looking for that BHAV on. Running in current stack you could more or less take for granted - it's just a call to be executed like any other BHAV that might have been local or semiglobal.

dizzy2
22nd Oct 2005, 9:22 AM
... there is no further way of saying which object to start looking for that BHAV on.

The way of saying that is what the value of Stack Object or Me is before you perform the RTBN. If you "run in Stack Object's stack", that will perform the behavior of the object whose ID is currently in Stack Object (whose name is found in the STR#).

Inge Jones
22nd Oct 2005, 9:27 AM
Dizzy are you sure? That's not what I would normally understand from that terminology - although it's always possible the phrase is being used to use something different than I would mean by it. For example, I have always thought "running in my stack" meant running (anything) as part of my process, not running a method stored on me.

dizzy2
22nd Oct 2005, 9:35 AM
I can only infer what I'm seeing in the objects.package itself. Right now, that code is telling me that this is how it works. *shrug*

Inge Jones
22nd Oct 2005, 9:40 AM
Well perhaps it does, and it's just confusingly expressed. I've posted a question to Tom in the hopes he has further light to shed.

On the other hand, if anyone reading this thread has actually made a mod and found themselves being able to successfully specify which object to obtain the BHAV (not the string) from, I'd love to hear. The true test would be to name two CT BHAVs exaxtly the same name but have them doing different things so you can tell if the right one ran. I could try that myself sometime I suppose.

dizzy2
22nd Oct 2005, 10:29 AM
I think you're getting confused between the "stack" and the "Stack Object ID" (which are two completely different things). Let me think of a better way to describe this...

Operand 6:

0 = push onto the stack used by Stack Object ID
1 = run in the stack used by the "Me" object (aka My Object ID)
2 = run in the stack used by Stack Object ID

(The "stack" refers to the actual stack itself, and "Stack Object ID" refers to the generic parameter variable which unfortunately was called "Stack Object").

Inge Jones
22nd Oct 2005, 10:57 AM
I feel sure we're saying the same thing, ie I am used to the "stack" meaning the current process itself, with each function/method/BHAV call being a push onto the stack, and the return of the call being a pop from the stack. That is why you can set the Stack Object to be something different in a called BHAV and it returns to what it was before when that BHAV returns.

But I cannot see any connection between this, and what object actually owns the method/BHAV. For example, in some OO languages you would call a method on another object by <objectID>.<method> but it would still run as part of the process owned by your current "stack" or process, which can be owned by a completely different object.

dizzy2
22nd Oct 2005, 2:27 PM
I think I see what you're asking. The "owner" object for the "method" being called is determined at runtime. When you compose the behavior, you either assign Stack Object ID to some object ID value or simply use the Me object ID, then do the RTBN.

In the case of the Stack Object ID, this is usually the result of a previous Set to Next or is passed to the behavior in a parameter (or something like that), and in the case of the Me object, this can be any Person object on the current lot that is interacting with the object that is performing the RTBN.

Inge Jones
22nd Oct 2005, 2:33 PM
I see. Well the call is not particularly useful then, because I wouldn't want to have to change the stack object just to find the code, having already set it to the object I want the code to act *upon* :)

Looks like I am just going to have to define my own global BHAVs after all. I'm starting at 0x900 so that shouldn't clash with anything. I hope BHAVs in that range will run when I come to test it...

dizzy2
22nd Oct 2005, 2:37 PM
I see. Well the call is not particularly useful then, because I wouldn't want to have to change the stack object just to find the code, having already set it to the object I want the code to act *upon* :)

Are you sure you understand what I'm saying? Because I have no freakin' idea what you're talking about.

Inge Jones
22nd Oct 2005, 2:51 PM
Probably not, but such are the limitations of the human language. Now if we were speaking a computer language, we could probably run a diff on the two of us and see which bits weren't calling the same parsing routines :D

Inge Jones
23rd Oct 2005, 9:29 AM
Ok, Tom says the BHAV is found on the Stack Object, so *if* that was what you were trying to say, then I understood you correctly. It's still annoying to have to change Stack Obj ID at the last moment though, under some circumstances - although at least one of the things I would be wanting to use RTBN for it's ideal to do that as I would be wanting it set to that anyway. And besides, now we can use more flexible parameters to the calls, I can always stuff the object I did want as Stack Obj into one of those.

dizzy2
2nd Nov 2005, 12:56 PM
Just as an update (thanks to Shy), the stack frame you use is designated by the 6th operand this way:

0 = run in my stack
1 = run in Stack Object's stack
2 = push onto my stack

The bits for 3rd operand byte have this meaning:

bit 0 = global STR#, bit 1 = semi-global STR#,
bit 2 = ignore global trees, bit 3 = ignore semi-global trees
bit 4 = specify params, bit 5 = use current params

The way the SimAntics processor finds the BHAV tree is that it examines the "Stack Object" private trees, then if it doesn't find the tree there it looks at the semi-globals for that object, then it looks for a global tree.

If you set bit 3 in the above operand or if you don't have a semi-global for that object, the processor will not look for a tree there.

If you set bit 2 in the above operand the processor will not look for a global tree of that name.

In any case, if the SimAntics processor does not find a tree with that name, the RTBN will return false.

ebruere
4th Nov 2005, 8:04 PM
There are basically two uses of the RTBN function :

1- calling a bhav of Sto's object
1- calling dynamically a bhav of the current object

You chose the name from local,semi or global ( relative to caller )
The game searches first in the local bhavs, then in the semi and last in the globals (relative to target ).
The main usage of this is defining a template behavior in the semiglobals of an object category, and overriding the behavior in the locals of specific objects.

jase439
6th Nov 2005, 8:37 AM
I haven't followed this thread for almost 2 months now *lol* I should point out, I ultimately discovered the hard way that if you call RTBN from inside an interaction, just like check trees, you cannot invoke a primitive which yields (Idle, Wait for Notify, Go To Routing Slot, etc.). In many cases, I discovered an error will be generated inside the called tree and RTBN will silently swallow the error and return false to the caller with no indication of what went wrong. There is some logic to this if you think about it. If you're yielding then you're attempting to do something asychronously, which in this case, the best solution is to prefer Push Interaction over RTBN.

ebruere: Welcome back. We thought you had fallen off the ends of the earth.

dizzy2
6th Nov 2005, 4:20 PM
I wonder if this could be the cause of those otherwise unexplained "Stack number out of range." errors I've seen on various things. Perhaps its not that anything in the function is literally out of "range" as defined by the function. Perhaps what it really means is that the stack pointer itself has produced a range error.

ebruere
9th Nov 2005, 2:10 PM
Dizzy,
The "Stack number out of range" means you are using a Local that does not exist. Change the max number of locals in the BHAV.

Jase,
During some interactions, the Sim is flagged as "Uninterruptible". This disables calls like "Idle" or "go to routing slot"
You have to save "my person data 47", set it to 1 before the call, and restore the value after the call.
My PC had fallen off the ends of the earth. Processor, power supply and Graphic card OUT :(( I just got a decent replacement ( and the two EPs :o) )

Inge Jones
10th Nov 2005, 10:19 AM
I am making a semi-global patch, and want to call a BHAV which is on one of my own objects.

I didn't want to add the new string to the semiglobal strings, and would prefer to put the calling string on the object that holds the BHAV I want to call. Is this possible?

ebruere
10th Nov 2005, 3:30 PM
No, the string can only use the caller's locals.
But you can use ANY existing global or semi-global string and rename your bhav to match this string.

Inge Jones
10th Nov 2005, 3:31 PM
Hey that's quite an ingenious work-around, thanks for the idea :D

dizzy2
10th Nov 2005, 6:36 PM
Dizzy,
The "Stack number out of range" means you are using a Local that does not exist. Change the max number of locals in the BHAV.

No offense, but I'm not retarded. What I'm referring to is this:

Object id: 924
name: Lamp - Wall - Pool - New - 1, 0 - Lower
Stack size: 5
Error: Stack number out of range.
Iterations: 0
Frame 4:
Stack Object id: 924
Stack Object name: Lamp - Wall - Pool - New - 1, 0 - Lower
Node: 2
Tree: id 8201 name 'Action - Do Fades' version 31
from LampGlobals
Prim state: 0
Params: 924 1 100 15 Locals:
Frame 3:
Stack Object id: 924
Stack Object name: Lamp - Wall - Pool - New - 1, 0 - Lower
Node: 3
Tree: id 8207 name 'Action - Fade ON' version 5
from LampGlobals
Prim state: 0
Params: 924 Locals:
Frame 2:
Stack Object id: 924
Stack Object name: Lamp - Wall - Pool - New - 1, 0 - Lower
Node: 10
Tree: id 8198 name 'Function - Init' version 32
from LampGlobals
Prim state: 0
Params: Locals:
Frame 1:
Stack Object id: 0
Node: 0
Tree: id 4097 name 'Function - Init( Stub )' version -32757
from Lamp_Wall_Pool
Prim state: 0
Params: Locals:
Frame 0:
Stack Object id: 0
Node: 0
Tree: id -1 name 'No behavior' version 0
from
Prim state: 1
Params: Locals:

Please pay attention, here. Notice, for example, that there are no hacks (that I know of, anyway) that replace "Action - Do Fades" tree.

This is the Maxis tree:

# Group = 0x7F60C397, Instance = 0x2009
# Title = Action - Do Fades
#
# Format = 8007, Params = 4, Locals = 0
# Tree type = 0, Header flag = 4, Tree version = 1F (31)

Now, explain to me exactly how you can produce that Object Error, if not the way I explain it.

christianlov
10th Nov 2005, 7:12 PM
I observed similar things several times too.... I think it's not about numbers of locals or params.... (don't know) -_-

ebruere
10th Nov 2005, 8:57 PM
Dizzy, the error here is produced during the call to the "Change light" primitive.
I don't know how params are sent in this case, but error is during the call, trying to send a local. If the error were later during exec of the primitive, you would have had "Undefined transition"

The message for a problem with the stack is "Stack overflow" or "stack underflow"
Ending the loop in the "Main" bhav of an object will cause the underflow.

dizzy2
10th Nov 2005, 9:43 PM
###
# Group = 0x7F60C397, Instance = 0x2009
# Title = Action - Do Fades
#
# Format = 8007, Params = 4, Locals = 0
# Tree type = 0, Header flag = 4, Tree version = 1F (31)

0: Param 1 > 0; true: 1, false: 1
1: Temp 1 := Param 3; true: 3, false: error
2: Change Light: on object in Param 0, Targeting all lights on Object, Fade duration in Temp 1, Intensity in Temp 0; true: 4, false: error
3: Temp 0 := Param 2; true: 2, false: error
4: Temp 0 := Param 2; true: 5, false: error
5: Change Light: on object in Param 0, Targeting all lights on Object, Fading over a duration of 0 ticks, Intensity in Temp 0; true: true, false: error

Okay, where precisely is this "local" usage?

Inge Jones
10th Nov 2005, 11:40 PM
Maybe the parsing of the call isn't complete/accurate in your output? I mean I don't have any idea if it is, but that could be one theoretical reason why you're getting an error connected with a local var in the call.

dizzy2
11th Nov 2005, 3:21 AM
Inge, have you lost it? That's a Maxis-designed tree, not mine. Think about it.

If that failed to work, it would error EVERY TIME A LIGHT TURNED ON.

The error I'm getting is NOT because of any mythical "local" variable that wasn't designed to be there in the first place. Jeez.

Inge Jones
11th Nov 2005, 7:21 AM
Dizzy why don't you post your actual listing (operator: operands) so we can look at it next to the Disasim output?

It may not be me and Ebruere who are going mad, it might be the Maxis interpreter/compiler or however it does it. We might get a clue about what it *thinks* it's meant to be doing.

dizzy2
11th Nov 2005, 8:30 AM
Inge, please. Are you even bothering to read my posts?

I did *******NOT******* modify that tree in any way. Look it up yourself.

THIS IS A MAXIS TREE. MAXIS. <-- Look

Inge Jones
11th Nov 2005, 9:15 AM
Sorry Dizzy, I was mixing what you were calling with what what you were calling was calling. Still it would be interesting to see your original call to Action Do Fades, in terms of operator: operands

For example, Change Light may implicitly take Callers Params

dizzy2
11th Nov 2005, 5:28 PM
*double sigh*

That would be extremely convenient, and I wouldn't have bothered mentioning it if that were the case, as the problem would have become quite easy to solve at that point. Part of the problem here is that I did *not* call that tree. My mods have NOTHING to do with that error.

Inge Jones
11th Nov 2005, 5:32 PM
So how come it's giving you an error? I play with the debugging on all the time and I don't get object errors from Maxis code. I mean why do you need to "solve" it if it's not your problem?

dizzy2
11th Nov 2005, 11:30 PM
So how come it's giving you an error? I play with the debugging on all the time and I don't get object errors from Maxis code. I mean why do you need to "solve" it if it's not your problem?

Somehow I don't think the important thing is figuring out who to blame.

I think the important thing is that it did happen, and this is why I think it did:

Because Maxis does not call "stub" Init the same way as regular Inits. I think they assume that you're never going to have Idle time, and the Idle time is probably occuring in the fade on the Light tree there. This is a potential problem for any object that uses the "stub" Init function, assuming I'm right about this.

christianlov
12th Nov 2005, 4:22 AM
I think it's somewhat natural for Inge to think so. You know, this kind of thing just doesn't happen in everybody's game. I think probably she never experienced this thing. Well, It's not related with the matter discussed above, but I see my sims are making errors and disappear when there is a sim who die platinum. They showed a pretty strange error when they saw the Maxis made hoola dancers. And it never happened before NL and it's just ridiculous. Of course, this happens with no hacks too. Anyway these things are weird -_-;;

Inge Jones
17th Nov 2005, 8:04 AM
My mods have NOTHING to do with that error.

http://www.moreawesomethanyou.com/smf/index.php?topic=1437.0 finally explains the problem arose in the context of one of your hacks. It doesn't cause a problem in the game normally. Instead of resorting to telling people they are going mad when they're only trying to take an interest in helping you, why not be prepared to explain the background a little? Otherwise it's like going to the doctor saying you have a pain in your back, but not helping the investigations by explaining you fell down the stairs the day before.

I am not saying your hack *caused* the problem, but it looks like Ebruere and I weren't so insane after all to be at least enquiring about context.

ebruere
18th Nov 2005, 1:29 AM
I think that during the init and some time after, the object is not yet fully existing.
I've had a problem with a ring I'm creating. I create the ring directly in the finger's slot, and test the slot just after that. result is zero !! with testing cheat, when the message appears, I can see the ring on the finger, the log tells me the ring exists and is contained in the slot.
I've solved the problem by creating the ring "out of world", then Sto ID is OK, I can set the attributes as needed, and then I "snap into" the slot.

I think that some calls require a tick to execute, some will execute in a new thread and allow you to continue. There are some short Idle instructions sometimes in maxis code probably to solve this problem.

dizzy2
19th Nov 2005, 7:24 AM
deleted... dammit

christianlov
19th Nov 2005, 7:36 AM
Deleted too. Let's talk about something else please.

dizzy2
19th Nov 2005, 7:39 AM
I want to not be arguing about this because it isn't helpful. Just stop defending your positions, please.

christianlov
19th Nov 2005, 7:51 AM
Okay, let me say one thing. I don't understand what is so important here. Please stop it.