Jump to content

placeatme + setpos from terminal?


davidlallen

Recommended Posts

I have a set of six machines, each with a terminal and an output tray. When the player does the right thing with the terminal, a terminal script runs and creates a different item at each machine. The item is supposed to appear in the output tray. Sometimes this works, sometimes it doesn't, so I need to figure out a different approach. When it doesn't work, the item appears in an unexpected location, sometimes at the player's feet, sometimes stuck inside the machine itself. Then it may go flying away, or be wedged along an edge of the machine, or some other bad problem.

 

Here is the useful bit of the terminal script:

 

ref rPart
ref rFab
ref rItem

; choose proper part based on which terminal
if getisreference TDGFabCoreRef
set rPart to TDGPartCentralCore
... check for the other five machines ...
else
set rPart to TDGPartLimbActivator
endif

; get position for drop
set rFab to getlinkedref
set TDGGenQuest.iLevel8X to rFab.getpos x
set TDGGenQuest.iLevel8Y to rFab.getpos y
set TDGGenQuest.iLevel8Z to rFab.getpos z + 128

; drop item and set position
set rItem to placeatme rPart 1
rItem.setpos x TDGGenQuest.iLevel8X
rItem.setpos y TDGGenQuest.iLevel8Y
rItem.setpos z TDGGenQuest.iLevel8Z

 

The "placeatme" wiki entry says you should not use other commands in the same frame as placeatme. But sometimes the items shows up in the correct location above the output tray, which is the linked reference of the terminal. A terminal script does not allow "begin gamemode" so I cannot conveniently wait a frame, and then move it. Since there are six machines, I can't cheat with one quest script; it has no way to know which item is needed.

 

How can I arrange to consistently move this item to the output tray after creating it?

Link to comment
Share on other sites

Un-named scripts, like terminals or packages or dialog result scripts, don't have any "begin". Also I have learned (in this thread) that local variables should never be used in these scripts due to memory corruption. So I don't think a "begin gamemode" in a terminal script would work, since I would need a local timer variable.

 

The container is a good idea, but it's a bit more of a change, because of some other things in my mod. I'll keep that idea on the back burner for a little while.

 

Is there a way to trigger a script and pass variables? I need to set the rPart and rItem when I still have access to the terminal item, but then I need to wait a frame.

Link to comment
Share on other sites

You should set some quest variable in the terminal script to tell some "quest script" to do something

 

like so, in terminal:

set Quest.Dosomething to 1
set Quest.myArg to getself

then in quest script:

short Dosomething
ref myArg 

begin gamemode


if Quest.Dosomething == 1
set Quest.Dosomething to 0
; Code to do something here...
endif

end

Edited by kert349
Link to comment
Share on other sites

Waiting a few frames after the PlaceAtMe, before doing SetPos functions, is important if you want consistent results. So using the terminal result script to trigger variables in a fast quest or object script is what you need to do this.

If you don't want any doubt as to how many frames you have to wait, you can use the condition:

 

if placedItemREF.HasLoaded3D == 1

Before using SetPOS functions.

Link to comment
Share on other sites

You should set some quest variable in the terminal script to tell some "quest script" to do something

Thanks, that is working. It is *almost* like calling a subroutine. But, in case you ever had two calls active at the same time, there is no way to know what would happen.

 

@ blove, that is a good solution for a single item. But in my case, the item could be fabricated multiple times, so I need placeatme.

 

@ rickerhk, the wiki page on hasloaded3d is basically empty. I am not quite sure what it is testing. Is it testing to see if the model is loaded off disk and rendered? For example, the same type of thing that "begin onload" checks? Then it could be that some instance of the model is already rendered, in which case this would immediately return true. In my case, a previous item could be fabricated and sitting there, when I fabricate a second one. Is this testing for the completion of "placeatme", which seems a little different from loading? In my current approach, I have simply set the quest update delay to 0.1 sec and made sure "setpos" comes on the second call to the script. Does this seem safe enough?

Link to comment
Share on other sites

But, in case you ever had two calls active at the same time, there is no way to know what would happen.

There is only one script thread in the running game so your call to the script will be able to 'clean up' before the next call to it. If you have multiple objects that need servicing, then you should give them their own set of variables in the script.

 

@ rickerhk, the wiki page on hasloaded3d is basically empty. I am not quite sure what it is testing.

Is it testing to see if the model is loaded off disk and rendered? For example, the same type of thing that "begin onload" checks? Then it could be that some instance of the model is already rendered, in which case this would immediately return true.

In my case, a previous item could be fabricated and sitting there, when I fabricate a second one. Is this testing for the completion of "placeatme", which seems a little different from loading?

 

You would be testing the specific reference that you obtained with PlaceAtme to see if it's has finished loading it's 3D info into the gameworld/current cell. I'm pretty sure but not verified that the 'On Load' script block and 3D loading are not necessarily synchronized, since you can have a whole cell of objects loading 3D at the same time, but the scripts on them are running sequentially. I've used hasloaded3d on actors when moving them into a cell to make sure they are rendered before doing something like applying a special effect on them. But maybe it's overkill for just testing PlaceAtMe. But that's me - script overkill ;)

 

In my current approach, I have simply set the quest update delay to 0.1 sec and made sure "setpos" comes on the second call to the script. Does this seem safe enough?

 

I'm doing it this way and it works fine.

 

 

 

 

Link to comment
Share on other sites

There is only one script thread in the running game so your call to the script will be able to 'clean up' before the next call to it. If you have multiple objects that need servicing, then you should give them their own set of variables in the script.

There is only one instance of a quest. Suppose I attach this quest script to an object which has several instances, and the quest script has a timer to sequence several actions and runs for a few seconds. Suppose the user activates several instances in quick succession. The quest variables will be overwritten and something very unpredictable will happen. So this technique must be used cautiously.

 

I've used hasloaded3d on actors when moving them into a cell to make sure they are rendered before doing something like applying a special effect on them. But maybe it's overkill for just testing PlaceAtMe. But that's me - script overkill ;)

For an actor, there is likely only one instance. For an object which has several instances, one may already be loaded and rendered in this cell. Then does the function instantly return true, or does it wait until the placeatme of this instance is done?

Link to comment
Share on other sites

There is only one instance of a quest. Suppose I attach this quest script to an object which has several instances, and the quest script has a timer to sequence several actions and runs for a few seconds. Suppose the user activates several instances in quick succession. The quest variables will be overwritten and something very unpredictable will happen. So this technique must be used cautiously.

In this case it may be better to use an object script on the spawned item so they can each have their own timer and variables.

 

For an actor, there is likely only one instance. For an object which has several instances, one may already be loaded and rendered in this cell. Then does the function instantly return true, or does it wait until the placeatme of this instance is done?

You are getting the specific reference of the item when you run:

 set rItem to placeatme rPart 1

rItem is not a baseID, because base forms are never loaded in the game world. Just references to base forms.

rItem.Hasloaded3D refers only to that instance of the base object.

 

 

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...