Jump to content

DOWNLOAD MODS

Are you looking for something shiny for your load order? We have many exclusive mods and resources you won't find anywhere else. Start your search now...

LEARN MODDING

Ready to try your hand at making your own mod creations? Visit the Enclave, the original ES/FO modding school, and learn the tricks of the trade from veteran modders...

JOIN THE ALLIANCE

Membership is free and registering unlocks image galleries, project hosting, live chat, unlimited downloads, & more...

[Solved] Call to PositionCell consistenly CTD's Oblivion


DeadHerring
 Share

Recommended Posts

Hey everyone. I've recently run into an aggravating and puzzling issue. I have an activator object that I'm using as a text input handler in the OBGEv3.1 Standalone Effects menus. This is originally located in a separate "assets" cell and moved to the player when needed. However, if I try to move it back to the assets cell with PositionCell (to get it out of the players "active" radius and save a few CPU cycles) the game CTD's every single time. What's puzzling is that I'm using the exact same technique for the root menu launcher without any problems.

This isn't a deal-breaking problem. It doesn't matter that much if the text input handler object is active, the bulk of the code is nested in conditionals anyway. It's just annoying. And perplexing. I know that doing much of anything with persistent references has caveats, but why the consistently inconsistent behavior? If simply moving a persistent ref from one cell to another was going to break the game, we'd be in a lot of trouble. I'd almost have to guess there's a bug with PositionCell. I'm debating whether or not to stop using PositionCell on the root menu launcher object. It works on my game install and load order, etc., but is someone else going to have issues?

Any advice would be appreciated. Thanks in advance!

Edited by DeadHerring
Link to comment
Share on other sites

No, the call is made from an unattached function script. The function script is called from the menu system's quest script, which fetches its ScriptID from the top of the page stack (an array). Not sure how that would affect anything, but that's the context. I'll double-check to make sure that the script isn't doing anything, but I'm pretty sure it's not. It shouldn't be by that point.

**

I've double-checked the object script for the text input handler, and I'm not seeing anything obvious. It has a GameMode block with a conditional so technically I suppose it's always doing something (I'm pretty sure I know what you meant, though). Of course, the root launcher obj has one too. Other than that it only has MenuMode and OnActivate blocks.

Here's the object script:


ScriptName OBGETextInputOS

;

; Text input handler


short		activated

short		selection

string_var	input

string_var	dialogText

ref		CallBack


Begin OnActivate

	If Eval (!dialogText)

		Let dialogText	:= (Call MenuSysAPIGetSystemArg "DialogText")->DialogText

		Let CallBack	:= (Call MenuSysAPIGetSystemArg "CallBack")->CallBack

	EndIf

	OpenTextInput $dialogText 0 120

	Let activated := 1

End


Begin MenuMode 1001

	If (activated)

		UpdateTextInput

	EndIf

End


Begin GameMode

	If (activated)

		Let selection := GetButtonPressed


		If (selection == 0)

			Let activated := 0

			Let input   := GetInputText

			Call MenuSysAPISetSystemArg (ar_Map "Input"::input)

			CloseTextInput

			Call CallBack ar_Null

		ElseIf (selection == 1)

			Let activated := 0

			Call MenuSysAPISetSystemArg (ar_Map "Input"::"cancel")

			CloseTextInput

			Call CallBack ar_Null

		EndIf

	EndIf

End

Here's the function script:

ScriptName OBGETextInputPageController

;

; Controls the behavior of the text input pages.

;

; Signature: (void) OBGETextInputPageController (Ref:StringMap)


array_var argVector

array_var pageData

ref ProcessAndReturn


Begin Function { argVector }


	;=======Init======

	If Eval (MenuSysCoreQ.ControllerMode == "Init")

		Let ProcessAndReturn := argVector->ProcessAndReturnAL


		; Register self with call stack, cache page data and cleanup

;		Call MenuSysAPISetSystemArg (ar_Map "ScriptID"::OBGETextInputPageController "CallBack"::OBGETextInputPageController)

		Call MenuSysAPIRegisterPage "%e"

		Call MenuSysAPICachePageData (ar_Map "ProcessAndReturnAL"::ProcessAndReturn "ArgVector"::argVector)


		; Pass player input control to TextInputHandler and invoke TextInputHandler

		Let MenuSysCoreQ.ControllerMode	  := "Wait"

		Let MenuSysCoreQ.DeferInputProcessing := 1

		TextInputHandler.MoveTo player

		TextInputHandler.Activate player 1


	;=======Restore======

	ElseIf Eval (MenuSysCoreQ.ControllerMode == "Restore")

		; Pass player input control to TextInputHandler and invoke TextInputHandler

		Let MenuSysCoreQ.ControllerMode	  := "Wait"

		Let MenuSysCoreQ.DeferInputProcessing := 1

;		TextInputHandler.MoveTo player

		TextInputHandler.Activate player 1


	;=======Wait======

	ElseIf Eval (MenuSysCoreQ.ControllerMode == "Wait")

		; Retrieve cached data

		Let pageData		:= Call MenuSysAPIRetrieveCachedData

		Let ProcessAndReturn	:= pageData->ProcessAndReturnAL

		Let argVector		:= pageData->ArgVector


		; Move text input handler back to assets cell, reassert menu system input control and process return value

;		TextInputHandler.PositionCell 2052, 2047, 8132, 0, OBGEAssetCell

		Let MenuSysCoreQ.DeferInputProcessing := 0

		Call ProcessAndReturn argVector

	EndIf


End

Edited by DeadHerring
Link to comment
Share on other sites

Yeah, I've had that thought floating around the back of my head for awhile now, waiting for something I was doing with OBSE to break the game. Especially since I started working on this, which isn't that far from trying to use OB script like a programming language. At least it's a problem I can avoid.

I'll keep experimenting with it, maybe I'll notice something. The fact that the behavior is so consistent, with one case always crashing the game but the other never having a problem, suggests a pattern. I wonder if having the text input handler obj's OnActivate block triggered might have something to do with it. The root menu launcher obj doesn't have one, just a flag variable that's set by an inventory token and evaluated in the GameMode block.

Oh well, thanks for taking a look :). And for indirectly getting my thinking on what I hope is the right track!

Edited by DeadHerring
Link to comment
Share on other sites

PROBLEM SOLVED. If a moderator could put [solved] at the start of the subject line, that'd be great! Thanks!

[Edited]

You were right, I was trying to call PositionCell on an activator object that was still trying to do something. It's rather obvious in hindsight. Even though the callback to the function script looks like it would be the last thing that's done in both branches of the logic, it isn't. Any use of "Call" stops execution at exactly that point and defers execution until the called function script exits. Which means that in both cases it was still inside the logic structure when PositionCell was called.

I used to know a guy from Brooklyn who had a way of coming up with one-liners that really capture the feeling of the moment. For moments like these, I'd have to pick "I is a genius, yo!" :bagged:

Anyway, moving the call to PositionCell into a "cleanup" script that doesn't get called until the player exits the menu system stopped the CTD's cold. Hey, at least I finally figured it out. :clap:

Cheers! :toast:

Edited by DeadHerring
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...