4
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

336 lines
10 KiB

Scriptname _00E_PlayerhousingCurrentOManipulate extends ReferenceAlias
EffectShader Property _00E_PlayerHousingManipulationShader Auto
Sound Property UIMenuPrevNext Auto
Actor Property PlayerRef Auto
String Property CONTROL_TURN_LEFT = "Strafe Left" AutoReadOnly
String Property CONTROL_TURN_RIGHT = "Strafe Right" AutoReadOnly
String Property CONTROL_MOVE_UP = "Forward" AutoReadOnly
String Property CONTROL_MOVE_DOWN = "Back" AutoReadOnly
Int Property TRANSLATION_TURN_LEFT = 0 AutoReadOnly
Int Property TRANSLATION_TURN_RIGHT = 1 AutoReadOnly
Int Property TRANSLATION_MOVE_UP = 2 AutoReadOnly
Int Property TRANSLATION_MOVE_DOWN = 3 AutoReadOnly
Int Property STATE_IDLE = 0 AutoReadOnly
Int Property STATE_UPDATING = 1 AutoReadOnly
Int Property STATE_WORKING = 2 AutoReadOnly
Float Property ROTATION_SPEED_START = 15.0 AutoReadOnly
Float Property ROTATION_SPEED_FALLBACK = 20.0 AutoReadOnly
Float Property ROTATION_SPEED_MAX = 180.0 AutoReadOnly
Float Property ROTATION_SPEED_CHANGE_MOD = 0.25 AutoReadOnly
Float Property ROTATION_MAX = 90.0 AutoReadOnly
Float Property MOVEMENT_SPEED_START = 10.0 AutoReadOnly
Float Property MOVEMENT_SPEED_FALLBACK = 20.0 AutoReadOnly
Float Property MOVEMENT_SPEED_MAX = 200.0 AutoReadOnly
Float Property MOVEMENT_SPEED_CHANGE_MOD = 0.25 AutoReadOnly
Float Property MOVEMENT_MAX = 100.0 AutoReadOnly
Float Property FAST_TRANSLATION_SPEED = 1000000.0 AutoReadOnly
Float fObjectPosX
Float fObjectPosY
Float fObjectPosZ
Float fObjectAngleX
Float fObjectAngleY
Float fObjectAngleZ
Float fPlayerPosZ
Float fTablePosZ
Float fTranslationSpeed
Float fTranslationSpeedIncrease
Int iWorkingState
Int iCurrentTranslation
Bool bGamepadMode
Int iWatchedKeyCode
Int iTurnLeftKey
Int iTurnRightKey
Int iMoveUpKey
Int iMoveDownKey
Function Setup(ObjectReference curObjectRef)
ForceRefTo(curObjectRef)
iWorkingState = STATE_IDLE
bGamepadMode = Game.UsingGamepad()
If bGamepadMode == False
iTurnLeftKey = Input.GetMappedKey(CONTROL_TURN_LEFT, 0)
iTurnRightKey = Input.GetMappedKey(CONTROL_TURN_RIGHT, 0)
iMoveUpKey = Input.GetMappedKey(CONTROL_MOVE_UP, 0)
iMoveDownKey = Input.GetMappedKey(CONTROL_MOVE_DOWN, 0)
Else
iTurnLeftKey = 274
iTurnRightKey = 275
iMoveUpKey = 280
iMoveDownKey = 281
EndIf
If PlayerRef == None ; Just in case
PlayerRef = Game.GetPlayer()
EndIf
fPlayerPosZ = PlayerRef.GetPositionZ()
fTablePosZ = fPlayerPosZ + 64.0
GoToState("Working")
TryRegisterForKey(iTurnLeftKey, CONTROL_TURN_LEFT)
TryRegisterForKey(iTurnRightKey, CONTROL_TURN_RIGHT)
TryRegisterForKey(iMoveUpKey, CONTROL_MOVE_UP)
TryRegisterForKey(iMoveDownKey, CONTROL_MOVE_DOWN)
_00E_PlayerHousingManipulationShader.Play(curObjectRef)
EndFunction
Function TryRegisterForKey(Int iKeyCode, String control)
If iKeyCode > 0
RegisterForKey(iKeyCode)
Else
RegisterForControl(control)
EndIf
EndFunction
Function Shutdown(Bool bRegisterNewOffsets)
GoToState("")
UnregisterForAllKeys()
UnregisterForAllControls()
UnregisterForUpdate()
ObjectReference myRef = GetRef()
If myRef != None
_00E_PlayerHousingManipulationShader.Stop(myRef)
While iWorkingState != STATE_IDLE && iWorkingState != STATE_WORKING
Utility.WaitMenuMode(0.05)
EndWhile
If iWorkingState == STATE_WORKING
myRef.StopTranslation()
EndIf
If bRegisterNewOffsets
Float fNewOffsetAngleZ = myRef.GetAngleZ() - PlayerRef.GetAngleZ()
Float fNewOffsetPosZ = myRef.GetPositionZ() - PlayerRef.GetPositionZ()
(GetOwningQuest() as _00E_PlayerhousingMaster).RegisterNewHousingObjectOffsets(fNewOffsetAngleZ, fNewOffsetPosZ)
EndIf
Clear()
EndIf
EndFunction
State Working
Event OnKeyDown(Int iKeyCode)
TryStartTranslation(KeyCodeToTranslationMode(iKeyCode), iKeyCode)
EndEvent
Event OnKeyUp(Int iKeyCode, Float fHoldTime)
TryStopTranslation(KeyCodeToTranslationMode(iKeyCode))
EndEvent
Event OnControlDown(String control)
TryStartTranslation(ControlToTranslationMode(control), 0)
EndEvent
Event OnControlUp(String control, Float fHoldTime)
TryStopTranslation(ControlToTranslationMode(control))
EndEvent
Event OnUpdate()
; OnControlUp is not always properly triggered. Maybe OnKeyUp too. The code below is a workaround for that.
; For gamepads this failsafe is useless because Input.IsKeyPressed always returns False for controller buttons.
If iWatchedKeyCode > 0 && iWorkingState == STATE_WORKING
If Input.IsKeyPressed(iWatchedKeyCode)
RegisterForSingleUpdate(0.05)
Else
TryStopTranslation(iCurrentTranslation)
EndIf
EndIf
EndEvent
Event OnTranslationComplete()
; The previously started translation reached its end point
If iWorkingState != STATE_WORKING
Return
EndIf
iWorkingState = STATE_UPDATING
ObjectReference myRef = GetRef()
If iWatchedKeyCode <= 0 || fTranslationSpeedIncrease < 0.0
; Do nothing
ElseIf iCurrentTranslation == TRANSLATION_TURN_LEFT || iCurrentTranslation == TRANSLATION_TURN_RIGHT
Float fRotationAngle = GetNextTranslationStep(ROTATION_SPEED_MAX, ROTATION_SPEED_CHANGE_MOD, ROTATION_MAX)
fObjectAngleZ = myRef.GetAngleZ()
TurnTranslate(myRef, fRotationAngle)
iWorkingState = STATE_WORKING
Return
ElseIf iCurrentTranslation == TRANSLATION_MOVE_UP || iCurrentTranslation == TRANSLATION_MOVE_DOWN
Float fMoveZ = GetNextTranslationStep(MOVEMENT_SPEED_MAX, MOVEMENT_SPEED_CHANGE_MOD, MOVEMENT_MAX)
fObjectPosZ = myRef.GetPositionZ()
MoveTranslate(myRef, fMoveZ)
iWorkingState = STATE_WORKING
Return
EndIf
; Fallback
FinalizeTranslation(myRef)
UIMenuPrevNext.Play(PlayerRef)
iWorkingState = STATE_IDLE
EndEvent
EndState
Int Function KeyCodeToTranslationMode(Int iKeyCode)
If iKeyCode > 0
If iKeyCode == iTurnLeftKey
Return TRANSLATION_TURN_LEFT
ElseIf iKeyCode == iTurnRightKey
Return TRANSLATION_TURN_RIGHT
ElseIf iKeyCode == iMoveUpKey
Return TRANSLATION_MOVE_UP
ElseIf iKeyCode == iMoveDownKey
Return TRANSLATION_MOVE_DOWN
EndIf
EndIf
Return -1
EndFunction
Int Function ControlToTranslationMode(String control)
If control == CONTROL_TURN_LEFT
Return TRANSLATION_TURN_LEFT
ElseIf control == CONTROL_TURN_RIGHT
Return TRANSLATION_TURN_RIGHT
ElseIf control == CONTROL_MOVE_UP
Return TRANSLATION_MOVE_UP
ElseIf control == CONTROL_MOVE_DOWN
Return TRANSLATION_MOVE_DOWN
EndIf
Return -1
EndFunction
Function TryStartTranslation(Int iTranslationMode, Int iTriggerKeyCode)
If iTranslationMode < 0 || iWorkingState != STATE_IDLE
Return
EndIf
iWorkingState = STATE_UPDATING
iCurrentTranslation = iTranslationMode
iWatchedKeyCode = iTriggerKeyCode
ObjectReference myRef = GetRef()
fObjectPosX = myRef.GetPositionX()
fObjectPosY = myRef.GetPositionY()
fObjectPosZ = myRef.GetPositionZ()
fObjectAngleX = myRef.GetAngleX()
fObjectAngleY = myRef.GetAngleY()
fObjectAngleZ = myRef.GetAngleZ()
fTranslationSpeedIncrease = 0.0
If iCurrentTranslation == TRANSLATION_TURN_LEFT || iCurrentTranslation == TRANSLATION_TURN_RIGHT
If iWatchedKeyCode > 0
fTranslationSpeed = ROTATION_SPEED_START
TurnTranslate(myRef, fTranslationSpeed * ROTATION_SPEED_CHANGE_MOD)
Else
fTranslationSpeed = ROTATION_SPEED_FALLBACK
TurnTranslate(myRef, ROTATION_MAX)
EndIf
ElseIf iCurrentTranslation == TRANSLATION_MOVE_UP || iCurrentTranslation == TRANSLATION_MOVE_DOWN
If iWatchedKeyCode > 0
fTranslationSpeed = MOVEMENT_SPEED_START
MoveTranslate(myRef, fTranslationSpeed * MOVEMENT_SPEED_CHANGE_MOD)
Else
fTranslationSpeed = MOVEMENT_SPEED_FALLBACK
MoveTranslate(myRef, MOVEMENT_MAX)
EndIf
EndIf
If iWatchedKeyCode > 0 && bGamepadMode == False
RegisterForSingleUpdate(0.05)
EndIf
iWorkingState = STATE_WORKING
EndFunction
Function TryStopTranslation(Int iTranslationMode)
If iCurrentTranslation != iTranslationMode || iWorkingState != STATE_WORKING
Return
EndIf
iWorkingState = STATE_UPDATING
ObjectReference myRef = GetRef()
myRef.StopTranslation()
UnregisterForUpdate()
FinalizeTranslation(myRef)
iWorkingState = STATE_IDLE
EndFunction
Function TurnTranslate(ObjectReference myRef, Float fRotationAngle)
If iCurrentTranslation == TRANSLATION_TURN_LEFT
fObjectAngleZ -= fRotationAngle
Else
fObjectAngleZ += fRotationAngle
EndIf
myRef.TranslateTo(fObjectPosX, fObjectPosY, fObjectPosZ, fObjectAngleX, fObjectAngleY, fObjectAngleZ, FAST_TRANSLATION_SPEED, fTranslationSpeed)
EndFunction
Function MoveTranslate(ObjectReference myRef, Float fMoveZ)
If iCurrentTranslation == TRANSLATION_MOVE_DOWN
Float fNewZ = fObjectPosZ - fMoveZ
If fObjectPosZ > fTablePosZ && fNewZ < fTablePosZ
; A primitive "drop on the table"
fNewZ = fTablePosZ
fTranslationSpeedIncrease = -1.0 ; Stop on reaching fPlayerPosZ.
ElseIf fObjectPosZ > fPlayerPosZ && fNewZ < fPlayerPosZ
; A primitive "drop on the floor"
fNewZ = fPlayerPosZ
fTranslationSpeedIncrease = -1.0 ; Stop on reaching fPlayerPosZ.
EndIf
fObjectPosZ = fNewZ
Else
fObjectPosZ += fMoveZ
EndIf
myRef.TranslateTo(fObjectPosX, fObjectPosY, fObjectPosZ, fObjectAngleX, fObjectAngleY, fObjectAngleZ, fTranslationSpeed, FAST_TRANSLATION_SPEED)
EndFunction
Float Function GetNextTranslationStep(Float fSpeedMax, Float fSpeedChangeMod, Float fChangeMax)
If fTranslationSpeed < fSpeedMax
If fTranslationSpeedIncrease < 20.0
fTranslationSpeedIncrease += 5.0
EndIf
fTranslationSpeed += fTranslationSpeedIncrease
If fTranslationSpeed > fSpeedMax
fTranslationSpeed = fSpeedMax
EndIf
EndIf
Float fResult = fTranslationSpeed * fSpeedChangeMod
If fTranslationSpeed >= fSpeedMax || fResult > fChangeMax
Return fChangeMax
Else
Return fResult
EndIf
EndFunction
Function FinalizeTranslation(ObjectReference myRef)
; TranslateTo below prevents the object from twitching and becoming blurry when a translation ends
If iCurrentTranslation == TRANSLATION_TURN_LEFT || iCurrentTranslation == TRANSLATION_TURN_RIGHT
fObjectAngleZ = myRef.GetAngleZ()
ElseIf iCurrentTranslation == TRANSLATION_MOVE_UP || iCurrentTranslation == TRANSLATION_MOVE_DOWN
fObjectPosZ = myRef.GetPositionZ()
EndIf
myRef.TranslateTo(fObjectPosX, fObjectPosY, fObjectPosZ, fObjectAngleX, fObjectAngleY, fObjectAngleZ, FAST_TRANSLATION_SPEED, FAST_TRANSLATION_SPEED)
EndFunction