Jump to content
Our Domain Name Has Changed! Read more... ×
Sclerocephalus

God dammit Bethesda, or: why the Lakeview Manor weapon rack can't be fixed

Recommended Posts

It's this rack I am talking about:

Lakeview Manor Weapon Rack 1

 
The reasons for racks displaying certain items not in the expected position are roughly known: when the overall rotation around certain axes that has to be applied to the item to be placed on its node (overall rotation = rotation value of the plaque in the respective cell plus rotation value specified on the item's node) is +90° or -90°, the engine adds an additional 180° which makes the item appear upside down.
 
It's an engine bug, but there are ways to circumvent it: tweaking the rotation values on the item nodes a little or rotating the plaques themselves 1-2° out of their planes makes overall rotation values of +/- 90° very unlikely to occur. In many cases, this simple trick solved the problem. Not in this case, though. A while ago, SilentSpike has been experimenting with this strategy and managed to make the right-hand plaque work properly, but the left-hand plaque refused to cooperate.
 
Yesterday evening, when I was eventually mad as hell about those incredibly boring and malfunctioning Hearthfires houses, I decided to give some fixes another try and started rotating all three plaques stepwise around the y axis. The result was pretty much the same as that reported earlier by SilentSpike:

Lakeview Manor Weapon Rack 2

 
Increasing the rotation value had no effect on weapon placement, but when the rotation value was sufficiently high to be noticeable, I did see this:

Lakeview Manor Weapon Rack 3

 
Obviously, the placement of the left-hand plaque had never actually changed. It simply refused to accept the placement data overrides from the esp and stayed in the position specified in the Hearthfires.esm, while the right-hand plaque and the shield plaque were rotated as specified.
 
Now, what makes the left-hand plaque that particular ? Simple: Its reference is a property on the Bye-Bye-House script (it's also the enable parent for the shield plaque and the right-hand plaque, although that's less important in this context). Once placed in the game world, it can never be relocated.
 
It's actually not true that the plaque can't be fixed. The rotation trick works, but the fix is not retroactive. Once the plaque has been constructed, the game is over ...
 
After all, there are some interesting facts remaining, although not pleasing ones: there obviously are different degrees of persistemcy. In other words, you can always make things worse with an inappropriate script.
 
I'd also wager to assume now that the actual reason for our ongoing problems with the ebony blade and other items have nothing to do whether or not they are quest items or there are scripts running on them. It's probably just their reference appearing as a property in an obscure script. Maybe it's still possible to fix them after all ?

Share this post


Link to post
Share on other sites

The thing about Papyrus-level persistence (for lack of a better term) is that you can always get the CK to tell you which object has it listed as a property. So if the Ebony Blades were parked in some obscure script somewhere, the CK would still tell us.

 

So far as I'm aware, this level of persistence applies whether or not the affected object is enabled yet or not. It's always been my experience that these things are set in stone immediately at the start of the game. Which in some ways is actually a lot worse than Oblivion's persistence.

 

So anyway. If this rack is misbehaving because one half of it is a property-locked object what's stopping us from using an external script to reposition its coordinates?

Share this post


Link to post
Share on other sites

So far as I'm aware, this level of persistence applies whether or not the affected object is enabled yet or not. It's always been my experience that these things are set in stone immediately at the start of the game. Which in some ways is actually a lot worse than Oblivion's persistence.

 

Items can acquire the same level of persistency when they are linked to enable markers. I had this problem with the static hoe in the player's garden in Riften: repositioning it simply didn't work. While player home decoration enable markers appear to have this effect particularly often, this doesn't always apply: The above example shows that the shield and right-hand plaques (which are parented to the left-hand plaque) do not refuse to be relocated.

 

This is a phenomenon that still requires more investigation.

 

 

So anyway. If this rack is misbehaving because one half of it is a property-locked object what's stopping us from using an external script to reposition its coordinates?

 

Well, that's the last resort.

 

EDIT:

Forgot to add: An y rotation of +3 (applied to the three racks and their activators) will fix the problem. When you prepare the script, also move them all +1.5 units in the y direction. This is to make sure that the shield plaque's trigger will not overlap with the wall's collision mesh in its new position.

Share this post


Link to post
Share on other sites

Actually if that hoe is a movable static (MSTT record) then it won't move either since havok items like that bake their data into your save too. It was one of the rather conspicuous bugbears I ran into with early versions of Open Cities. None of them could be relocated.

Share this post


Link to post
Share on other sites

Another persistency effect:

http://www.afkmods.com/index.php?/gallery/image/1406-persistency-effect-in-the-ragged-flagon/

 

I assume that you did move the shelf out of the way properly when you added the bedroom to the Ragged Flagon, did you ? Well, at least in my game, the items on the shelf did not cooperate. I'm still trying to find out what made them persistent.

Share this post


Link to post
Share on other sites

They're Havok items. That was expected that they'd not cooperate in all cases. I suppose I should add a note to the changelog to expect it to happen on existing saves where the Flagon has already been visited. I'm not sure if it corrects to the new positions on cell reset or not.

Share this post


Link to post
Share on other sites

In another "God dammit" moment, get a load of this:

http://forums.bethsoft.com/topic/1462394-relz-skyui/?p=23032032

It's a Papyrus script vs. game engine bug. Values above 7F appear as negative numbers to Papyrus. So if you store references to forms from late-loading mods (or even the save file like user-created potions) some Papyrus functions don't work. What I don't understand is why passing the negative numbers back from Papyrus to the game doesn't work. They must have recreated a version of the Oblivion bug where all numerical global variables were really floats so you couldn't represent all of the values you would expect from a long type.

Why, Bethesda, WHY?

Share this post


Link to post
Share on other sites

Damn...

 

Is it possible to make 2 distinct racks types ? One designed to be oriented in the N/S axis, another in the E/W axis, then modifying the nodes directly in the mesh of the faulty one in order to 'cheat' the engine ?

Share this post


Link to post
Share on other sites

So. Imagine you have yourself a quest. One you need to keep regular updates running on. You initiate it with a RegisterForUpdate(30). In the OnUpdate() event, you have a few conditions to meet before calls to RegisterforSingleUpdateGameTime() are sent.

 

Sounds good, right? Well, what do you do when you forget to include an OnUpdateGameTime() handler? You make a mess, that's what. Why the hell are you even doing this if nothing comes of it?

 

Seasoned scripters don't make dumb mistakes like that, right? Well... I present to you this bug:

http://www.afkmods.com/index.php?/tracdown/issue/8708-college-of-winterhold-lecture-scenes-do-not-play-mgcollegelectureinfos/

MGCollegeLecturesQuestScript.psc

 

That's right, once you join the college that lectures quest is set on a 30 second update timer for the remaining life of your save. Busily stacking up RegisterforSingleUpdateGameTime() for various reasons with no OnUpdateGameTime() handler to bring them down. Even if you never wanted to join the college.

 

Anyone who has sufficiently advanced the MQ will have run into this. The fact that the stupid lectures themselves don't even work right is only the visible problem. All those unhandled calls are piling up on your stack every 30 seconds when a scene is not picked to play. And a scene will not be picked to play for 22 out of 24 hours every game day. You could be sitting on an untold number of them just waiting. Waiting for something that's never going to come.

 

Our very own script sleuth, PrinceShroob, dug into this mess after the subject came up in chat. Mind bogglingly bad. It'll obviously need a script rewrite. Because there are so many events that will have been registered with no resolution, the quest is simply going to have to be stopped so Papyrus can dump them all out, then reset, and then restarted if the player is a member of the College.

 

God dammit Bethesda!

 

(unless I'm horribly misunderstanding this, cause Shroob seems to agree with my assessment)

Share this post


Link to post
Share on other sites

Not even approaching the quality of the lectures bug, but one with significant consequences: It appears that a fair enough number of road encounter triggers do never trigger any encounter at all, because they are missing the properties to send the event to the story manager:

http://www.afkmods.com/index.php?/tracdown/issue/13902-wetriggerscript-problems-with-weenabled-off/

 

 

EDIT:

That's also a nice one: a recursion that runs along a linked reference chain and throws an error in each cycle because it has two commands backwards. Produces stacks of an impressive length on the log ...

http://www.afkmods.com/index.php?/tracdown/issue/13787-dlc2-qf-dlc2dunhaknirtreasure-02024002-object-reference-has-no-3d/

Share this post


Link to post
Share on other sites

Might be placebo, but I manually shut down the MGCollegeLectureInfos quest and the game seemed to have less trouble responding to Papyrus events.

 

Anyway, to add to all this after running a "dps" command from the console:

[10/10/2013 - 02:50:53AM] Dumping stack 18906738:
[10/10/2013 - 02:50:53AM]     Frame count: 3 (Page count: 2)
[10/10/2013 - 02:50:53AM]     State: Waiting on other stack for return (Freeze state: Freezing)
[10/10/2013 - 02:50:53AM]     Type: Normal
[10/10/2013 - 02:50:53AM]     Return register: None
[10/10/2013 - 02:50:53AM]     Has stack callback: No
[10/10/2013 - 02:50:53AM]     Stack trace:
[10/10/2013 - 02:50:53AM]         [ (0300AEB6)].SPELL.RemoteCast() - "<native>" Line ?
[10/10/2013 - 02:50:53AM]             IP: 0
[10/10/2013 - 02:50:53AM]             [param1]: [ObjectReference < (FF001D9D)>]
[10/10/2013 - 02:50:53AM]             [param2]: [Actor < (00000014)>]
[10/10/2013 - 02:50:53AM]             [param3]: [ObjectReference < (FF001DAB)>]
[10/10/2013 - 02:50:53AM]         [None].DLC1MagicCastFromSunScript.CastSpellFromSun() - "<savegame>" Line ?
[10/10/2013 - 02:50:53AM]             IP: 1256    Instruction: 28
[10/10/2013 - 02:50:53AM]             [bWeWantToMiss]: True
[10/10/2013 - 02:50:53AM]             [::temp15]: [STATIC < (0000003B)>]
[10/10/2013 - 02:50:53AM]             [::temp16]: [ObjectReference < (FF001DAB)>]
[10/10/2013 - 02:50:53AM]             [::temp17]: 861.304810
[10/10/2013 - 02:50:53AM]             [::temp18]: -59688.488281
[10/10/2013 - 02:50:53AM]             [::temp19]: [-38647.828125, -59688.488281, 4730.522461]
[10/10/2013 - 02:50:53AM]             [::temp20]: 4730.522461
[10/10/2013 - 02:50:53AM]             [::NoneVar]: None
[10/10/2013 - 02:50:53AM]             [::temp21]: [Cell <Wilderness (00009B9B)>]
[10/10/2013 - 02:50:53AM]             [SpellCastXMarkerRef]: [ObjectReference < (FF001D9D)>]
[10/10/2013 - 02:50:53AM]             [TargetMarkerRef]: [ObjectReference < (FF001DAB)>]
[10/10/2013 - 02:50:53AM]             [PosX]: -41935.089844
[10/10/2013 - 02:50:53AM]             [PosY]: -61314.308594
[10/10/2013 - 02:50:53AM]             [position]: [-38647.828125, -59688.488281, 4730.522461]
[10/10/2013 - 02:50:53AM]         [None].DLC1MagicCastFromSunScript.OnUpdate() - "<savegame>" Line ?
[10/10/2013 - 02:50:53AM]             IP: 218    Instruction: 4
[10/10/2013 - 02:50:53AM]             [::temp8]: 1.551994
[10/10/2013 - 02:50:53AM]             [::NoneVar]: None
[10/10/2013 - 02:50:53AM]             [::temp9]: True

Indicating there's something really wrong with the Auriel's Bow script for shooting at the sun. Something I think this character has done all of once just to see what would happen.

 

So the question is, why is this always on the script stack? It's not throwing any errors, it's just occupying an awful lot of active script time because it's ALWAYS on the stack when I look.

Share this post


Link to post
Share on other sites

There are quite a number of large/messy/complicated scripts now that require some work:

Share this post


Link to post
Share on other sites

Add the entire mess of critter scripts to the pile too. I don't think our efforts have removed enough of the problems because my logs are still filling up with garbage from those.

Share this post


Link to post
Share on other sites

Wow ! My eyes were bleeding since Hearthfire release about 1 year ago, but what I'm actually seeing is an unexpected blessing !

 

Can you elaborate on the means/tricks you used to achieve this ?

Share this post


Link to post
Share on other sites

So. Imagine you have yourself a quest ... [ #@!ß*& ]  God dammit Bethesda!

 

Found a much better one:

Imagine you have an object reference 'Spawner' and need to choose a pair of random x/y coordinates at an arbitrary z angle and within a distance equal to or less than 'fLeashLength' from 'Spawner'. How do you calculate this ?

 

This is a function from the vanilla CritterDragonfly script, where someone is aimlessly trying to accomplish this:

Function PickRandomPoint()

	Float fLength = fLeashLength * 2.0

	Int Count
	Int MaxCount = 10


	fTargetX = 0.0
	fTargetY = 0.0

	While (fLength > fLeashLength) && (Count < MaxCount)
		fTargetX = RandomFloat (-fLeashLength, fLeashLength)
		fTargetY = RandomFloat (-fLeashLength, fLeashLength)
		fLength = Math.Sqrt (fTargetX * fTargetX + fTargetY * fTargetY)
		Count += 1
	EndWhile

	fTargetX = fTargetX + Spawner.X
	fTargetY = fTargetY + Spawner.Y
	
	; Now pick a random Z
	fTargetZ = RandomFloat (0.0, fHeight)
	fTargetZ = Spawner.Z + fTargetZ
	
	; Pick random target angle
	fTargetAngleZ = RandomFloat (-180.0, 180.0)
	fTargetAngleX = 0.0
	
EndFunction

Of course, he could have chosen a random z angle first (quickly rewritten by myself):

Function PickRandomPoint()

	Float fLength = RandomFloat (0.0, fLeashLength)

	fTargetAngleZ = RandomFloat (-180.0, 180.0)
	fTargetAngleX = 0.0

	fTargetX = Spawner.X + fLength * Math.Cos (fTargetAngleZ)
	fTargetY = Spawner.Y + fLength * Math.Sin (fTargetAngleZ)
	fTargetZ = Spawner.Z + RandomFloat (0.0, fHeight)

EndFunction

EDIT:

For the very special kick, have a look at the CritterFish script where he tries to do the same in three dimensions, by selecting a random point whithin a cone (with a comment on MaxCount saying "how many times to try before giving up") ...

Share this post


Link to post
Share on other sites

Errors on the log - so what ?

 

An enlightening comment line from the vanilla CritterSpawn script:

 

    ;DREW - Added an extra safety measure for if the object is stuck in the spawn check loop while the 3d is not loaded
    ;    NOTE - is3dLoaded dumps an error when the 3d is not loaded, but the function still returns false which should
    ;        set bLooping to false and jump out of the bLooping While, at which point no additional errors will be thrown
 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Support us on Patreon!

×