Jump to content

In-Place Rotation with TranslateTo


niston

Recommended Posts

Well, It works, I can move the water plane with some debris, but the water looks almost transparent for some reason.

Could it have something to do with having water under the water plane?

 

Yeah, it's more like "it kinda works, but not really" right? I don't remember exactly what I saw, but I think it was something like the way water worked was wrong while/after it moved. TranslateTo with movable water works the way it should, on the other hand (and that's what Bethesda used for Weston). In my situation, the player has to jump into the water, so the things have to work in that context.

 

...Sorry for hijacking the thread, niston! :happy:

Link to comment
Share on other sites

Ye, having water under water looks quite strange from above and even stranger from below. Also, in the water lock, there is a spot near the upper door where you can walk on the ground and use the weapon while submerged *shrug* I'll maybe see about fading the additional water planes when the level is low.

 

I'd love for somebody with 3DSMax to make me a NIF, but such people seem hard to get by these days. For reference, I first tried using the unique water piece with the cutout that is used for the upper door. But it's not long enough to cover the lock's chamber, so requires at least one extra water plane anyways, negating any benefits of using it.

 

Btw the script Beth uses for the movable water in Weston is an absolute marvel of technology complexity. You can translate up to 128 water planes independently in any direction, at any speed to any angle, using multiple stages. And you can register objects to get notified when the water level changes. I checked it out the other day and was like "this looks like a german engineered car." :laugh: Also I wonder why they use said registration system instead of events for notification purposes. Maybe it was ported/reused from an older game that didn't have events?

 

Also, thread not hijacked as this all is somewhat relevant. Only the thread's title might not entirely match it's contents now.

Link to comment
Share on other sites

@DiodeLadder

Using the elevator helper looks like the water texture doesn't move at all while the water waves do, at the same time when you enter in to the moved water the view and the sounds are ok, but you can't swim or float until you reach the original height of the water.

 

Looking at the script attached to the water plane DN158_MoveableWater, which I assume is the water of Weston water treatment plant, even Bethesda uses TranslateTo to move the water plane.

So I guess is the only way to go.

 

@niston

I would move the terrain over the water height inside of the dam to avoid it.

 

About the custom nif, I've read that you can convert an .obj to .nif and vice versa using BodySlide, and if it doesn't need any collision it could be enough I guess. You can create .obj files in Blender, which is free. BodySlide also has import/export option for fbx files which you can create in Paint3d which is included in Windows 10.

 

Edit: I've tried exporting a water plane to fbx and load it in Paint3d but it doesn't work at all. So I would use Blender (which I'm going to try right now).

Edited by DieFeM
Link to comment
Share on other sites

custom-water-plane.png

The process works, but water planes actually have a collision node which determines if you fall or swim when you are in the water. So In my modified nif I got it to show the water, but in the part that I added there's no collision so you fall like if there's no water.

 

CustomWaterDamLock.nif

 

PS: I have no idea about using Blender, did it by deduction...

Edited by DieFeM
Link to comment
Share on other sites

I think the only real way to get it done properly is with 3DSMax. I've encountered a similar problem with custom NIFs that were made in CK, they sometimes had either wonky collision or none at all. I wonder tho if it were possible to use a collision box below some water without collision? Then again, player can not swim in water w/o collision - as became evident during your experiment with the unique water. :sad:

 

Altering the terrain in the lock to raise it above the water line crossed my mind. But if I do that, then things in the lock will run aground when the lock is empty. And if I keep my movable water over the raised terrain when the lock is empty, then that movable water won't match the height of the adjacent cell's water, leading to much more gruesome visual artifacts than the water under water creates.

Link to comment
Share on other sites

Here's my DoorController code, should anyone need it. It's essentially a finite state machine, concerned only with rotating a single door (which must be a MovableStatic) by using TranslateTo(). There is no control logic in it, as that is implemented at a higher abstraction level (LockController). You can probably tell by now that the Separation Of Concerns is a fetish of mine. Thus, two of these DoorControllers can be integrated into a single, synchronized gate by using a separate Class called GateController. I might post that one later on.

Scriptname ForestGroveSluice:FGS_DoorController extends ObjectReference
 
; custom scripting by niston 

; public interface 
CustomEvent FGS_Door_Open
CustomEvent FGS_Door_Closed
CustomEvent FGS_Door_Jammed
CustomEvent FGS_Door_Stopped
 
Float Property NormalAngle Auto Const
{ the normal (non-actuated) Z angle of the door, as it is placed on the map }
 
Float Property RotationAngle Auto Const
{ the difference between open/close angles (how far the door rotates between open and close positions) }
 
Float Property RotationSpeed Auto Const
{ rotation speed in units per step (how fast the door rotates) }
 
Bool Property RotationInverted Auto Const
{ rotation is inverted (useful for double doors such as the sluice) }
 
Bool Property NormallyOpen Auto Const
{ depends on normal (non-actuated) position of the door - set this to true if door must be rotated to close; likewise, set to false if door must be rotated to open }

; member vars
Float fTargetAngleZOpen
Float fTargetAngleZClosed
 
; initialization
Event OnInit() 
    ; calculate open/close angles from normalangle and initialize state
    If (NormallyOpen)
        fTargetAngleZOpen = NormalAngle
 
        If (RotationInverted)
            fTargetAngleZClosed = NormalAngle - RotationAngle
        Else
            fTargetAngleZClosed = NormalAngle + RotationAngle
        EndIf
 
        Debug.Trace("Initializing Door " + Self + " to Open state")
        GotoState("Open")
    Else
        fTargetAngleZClosed = NormalAngle
 
        If (RotationInverted)
            fTargetAngleZOpen = NormalAngle + RotationAngle
        Else
            fTargetAngleZOpen = NormalAngle - RotationAngle
        EndIf
 
        Debug.Trace("Initializing Door " + Self + " to Closed state")
        GotoState("Closed")
    EndIf
EndEvent 
 
; open state
State Open 
    Event OnBeginState(String oldState)
        Debug.Trace("Door " + Self + " is in state Open")
        SendCustomEvent("FGS_Door_Open")
    EndEvent
 
    Function Close()
        GotoState("Closing")
    EndFunction
EndState
 
; closed state
State Closed
    Event OnBeginState(String oldState)
        Debug.Trace("Door " + Self + " is in state Closed")
        SendCustomEvent("FGS_Door_Closed")
    EndEvent
 
    Function Open()
        GotoState("Opening")
    EndFunction
EndState
 
; opening state
State Opening
    Event OnBeginState(String oldState)
        Debug.Trace("Door " + Self + " is in state Opening"
        SetMotionType(Motion_Keyframed)
        TranslateTo(GetPositionX(), GetPositionY(), GetPositionZ(), GetAngleX(), GetAngleY(), fTargetAngleZOpen, 0.0, RotationSpeed) 
    EndEvent
 
    Event OnTranslationComplete()
        Debug.Trace("OnTranslationComplete")
        GotoState("Open")
    EndEvent
 
    Event OnTranslationFailed() 
        Debug.Trace("Door " + Self + " jammed while opening - OnTranslationFailed")
        GotoState("Jammed")
    EndEvent
EndState
 
; closing state
State Closing
    Event OnBeginState(String oldState)
        Debug.Trace("Door " + Self + " is in state Closing") 
        SetMotionType(Motion_Keyframed)
        TranslateTo(GetPositionX(), GetPositionY(), GetPositionZ(), GetAngleX(), GetAngleY(), fTargetAngleZClosed, 0.0, RotationSpeed)
    EndEvent
 
    Event OnTranslationComplete()
        Debug.Trace("Closing - OnTranslationComplete")
        GotoState("Closed")
    EndEvent
 
    Event OnTranslationFailed() 
        Debug.Trace("Door " + Self + " jammed while closing - OnTranslationFailed")
        GotoState("Jammed")
    EndEvent
 
    Function Stop()
        StopTranslation()
        GotoState("Stopped")
    EndFunction
EndState

; jammed state (TranslateTo() failed)
State Jammed
    Event OnBeginState(string oldState)
        Debug.Trace("Door " + Self + " jammed")
        SendCustomEvent("FGS_Door_Jammed")
    EndEvent
 
    Function Open()
        GotoState("Opening")
    EndFunction
 
    Function Close()
        GotoState("Closing")
    EndFunction
EndState

; stopped state (stop requested)
State Stopped
    Event OnBeginState(string oldState)
        Debug.Trace("Door " + Self + " stopped")
        SendCustomEvent("FGS_Door_Stopped")
    EndEvent
 
    Function Open()
        GotoState("Opening")
    EndFunction
 
    Function Close()
        GotoState("Closing")
    EndFunction
EndState

; empty state
Function ResetDoor()
    StopTranslation()
    If (NormallyOpen)
        SetAngle(GetAngleX(), GetAngleY(), fTargetAngleZOpen)
        GotoState("Open")
    Else
        SetAngle(GetAngleX(), GetAngleY(), fTargetAngleZClosed)
        GotoState("Closed")
    EndIf 
EndFunction
 
; dummy functions for empty state
Function Open()
    ; dummy
EndFunction
 
Function Close()
    ; dummy
EndFunction
 
Function Stop()
    ; dummy
EndFunction
Link to comment
Share on other sites

Thank you very much for sharing your script, niston! I'm not that advanced in scripting, and always appreciate seeing examples. :thumbsup:

 

One thing you might want to consider including is an ObjectReference Property that points to a NAVCUT, which gets enabled/disabled depending on the door open/closed state.

 

https://www.creationkit.com/index.php?title=NAVCUT

 

For example, the barn door used at Boston Police Rationing Site is using a platform helper to animate the door, and in closed state a NAVCUT gets enabled so that NPCs won't run into the door. In the case of lock gate, I think the navmesh for the top walkway should be disabled using NAVCUT when it is open, so that NPCs wouldn't try to go there.

 

 

@DieFeM, I've tried using translateto with a helper, and it worked great on something I needed a solution for. Thank you very much for the idea! :smile:

Link to comment
Share on other sites

Oh yes that is a very good proposition. I take it the NAVCUT could be placed in CK, so that the code can then simply enable/disable it through the property, based on open/closed state of the gate?

 

Altho I have placed a bunch of settlers and watched them, anticipating them falling to their deaths. It was a very disappointing 30 minutes...

 

Also, you sure thats at the PD rationing site and not at the warehouse even farther towards the end of the tracks? Where the strongroom is? Just asking because that PD rationing site door was non-functional for me, so I scrapped it and put some working doors there... I claimed the site, put a settlement and renamed it DC Warehouse, you see :smile:

 

Reading the link you posted, I wonder if this could be a problem perhaps:

 

 


NAVCUT boxes will only affect a character's pathing if they are present and enabled when the character has started pathing. If a NAVCUT box is enabled after a character has already started walking to a location, then they may not notice the change: they may walk right through the NAVCUT volume. Objects with NAVCUT data in their meshes seem to behave differently: followers will stop and restart pathing every time such objects are moved (e.g. by a script)

 

Would a collision box prevent NPC from walking through a freshly-enabled navcut? Is a navcut useful when there's a collision box?

Link to comment
Share on other sites

I have been just using scripts to enable/disable navcut depending on the state. I think having it in the property window could work as a reminder to put one in as well. :-) It's just a primitive collision box. You create a trigger box in render window, and in the reference window, there's "primitive" tab - here you'll find "collision layer" pulldown menu. You select "L-NAVCUT" there.

 

About the pathing - Argh, I guess there had to be a problem, lol. This may not be a problem with settlers, though, because they just wander around, instead of having clear destinations most of the time? I guess if you assign a settler to something on the other side, and open the gate after he/she started pathing (just to be a jerk, lol), that settler won't see the navcut primitive, according to the article.

 

Looks like checking "obstacles" check box in the object editor would enable the navcut feature in NIF, but I've never tried this. Directly editing nif may help doors, but in case of the lock doors, it's the walkway at the top, so this may not help.

 

There is also a problem of the NPCs that are already walking on the gate while it's opening as well. I wonder if you can use something like the settlement siren mechanics to move off the settlers before opening the gate?

 

 

...Maybe that was a warehouse close to rationing site? One of the warehouses around there had a barn door (made of static, attached to platformhelperfree01) connected to a switch that opened it. It's one of those things I've never noticed until I was looking at usage info for the helper in CK, lol.

Link to comment
Share on other sites

Oh, I might just as well have not found the switch and scrapped the doors in ignorance on my part, hehe.

 

I'm gonna try the navcut thing. And maybe the siren thing as well. Otoh, settlers are stupid dumbf*#@s that can't be helped anyways. If I put an extra collision box to prevent them from wandering through a navcut that's been enabled after they decided they have to use the armor workbench on the other side of the gates right now, then I've got a feeling they'll just happily teleport through that collision box, like they often do through locked doors and even walls (but seemingly never through an unintentional obstacle that prevents them from reaching their assigned work object).

 

I also think some blinkenlights would be in order, to signal of impending movement. Unfortunately, the only suitable lamp is in one of the workshop DLCs (the red industrial wall light). I don't feel like adding that dependency to Ragoda's settlement mod.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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