1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Robert TIMM (rti) <mail@rtti.de>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include "game_share/bot_chat_types.h"
33 #include "user_controls.h"
34 #include "../actions_client.h"
35 #include "../user_entity.h"
36 #include "../cursor_functions.h"
37 #include "../time_client.h"
38 #include "../interface_v3/interface_manager.h"
39 #include "../ingame_database_manager.h"
40 #include "../entities.h"
44 #include "../r2/editor.h"
54 using namespace NLMISC
;
61 extern UDriver
*Driver
;
63 extern CEventsListener EventsListener
; // Inputs Manager
68 // User Controls (mouse, keyboard, interfaces, ...)
69 CUserControls UserControls
;
72 H_AUTO_DECL ( RZ_Client_User_Controls_Update
)
75 // ----------------------------------------------------------------------------
76 static bool isSwimming()
78 if (UserEntity
!= NULL
)
79 return (UserEntity
->mode() == MBEHAV::SWIM
|| UserEntity
->mode() == MBEHAV::MOUNT_SWIM
);
87 return UserEntity
->isSit();
92 static bool isRiding()
95 return UserEntity
->isRiding();
104 //---------------------------------------------------
107 //---------------------------------------------------
108 CUserControls::CUserControls()
113 //---------------------------------------------------
115 // Initialize all the components.
116 //---------------------------------------------------
117 void CUserControls::init()
119 // Default Mode is Interface Mode.
120 _LastMode
= _Mode
= InterfaceMode
;
124 _RightClickStart
= 0;
126 _TimeBeforeMouseSlide
= 50;
127 _TimeLongClick
= 200;
144 _Start
= CVector(0,0,0);
145 _Destination
= _Start
;
149 _DirectionMove
= none
;
151 _Locked
= false; // Move is not locked.
154 _InternalView
= true;
156 _LastFrameBackward
= false;
157 _LastFrameForward
= false;
158 _LastFrameAutowalk
= false;
159 _LastFrameStrafeLeft
= false;
160 _LastFrameStrafeRight
= false;
161 _LastFrameTurnLeft
= false;
162 _LastFrameTurnRight
= false;
163 _LastFrameLeftButtonDown
= false;
164 _LastFrameMousePosX
= 0.f
;
165 _LastFrameMousePosY
= 0.f
;
170 _UserCameraDeltaYaw
= 0;
171 _ResetSmoothCameraDeltaYaw
= ResetCDYOff
;
173 _CurrentFrameFreeLookCalled
= false;
175 _RotateUserLRVelocity
= 0.f
;
176 _RotateUserUDVelocity
= 0.f
;
177 _RotateCameraLRVelocity
= 0.f
;
179 _MouseCaptured
= false;
181 _NeedReleaseForward
= false;
182 _NextForwardCancelMoveTo
= false;
186 void CUserControls::reset()
191 //-----------------------------------------------
192 // needReleaseForward :
193 //-----------------------------------------------
194 void CUserControls::needReleaseForward()
196 if( Actions
.valide("forward") )
198 _NeedReleaseForward
= true;
203 //-----------------------------------------------
205 //-----------------------------------------------
206 void CUserControls::autowalkState(bool enable
)
211 _DirectionMove
|= autowalk
;
212 // If not backward, default is forward.
213 if(!(_DirectionMove
& backward
))
214 _DirectionMove
|= forward
;
217 _DirectionMove
&= ~(autowalk
|forward
|backward
);
221 //-----------------------------------------------
223 // Main function of the Class -> Call it each frame.
224 //-----------------------------------------------
225 void CUserControls::update()
227 H_AUTO_USE ( RZ_Client_User_Controls_Update
);
231 // Reset the moving direction.
232 _DirectionMove
&= ~(left
| right
);
234 // if not locked, move
237 // What is the current _Mode ?
260 // Third Person View Mode
269 _LastFrameForward
= Actions
.valide("forward") && !_NeedReleaseForward
;
270 if( UserEntity
->mode() != MBEHAV::MOUNT_SWIM
)
272 _LastFrameBackward
= Actions
.valide("backward");
274 _LastFrameAutowalk
= Actions
.valide("toggle_auto_walk");
275 if( isSit() || UserEntity
->isAFK() )
277 if( _LastFrameForward
|| _LastFrameBackward
)
279 UserEntity
->sit(false);
280 UserEntity
->setAFK(false);
283 if (isSwimming() || isRiding())
285 _LastFrameStrafeLeft
= false;
286 _LastFrameStrafeRight
= false;
290 _LastFrameStrafeLeft
= Actions
.valide("strafe_left");
291 _LastFrameStrafeRight
= Actions
.valide("strafe_right");
293 _LastFrameTurnLeft
= Actions
.valide("turn_left");
294 _LastFrameTurnRight
= Actions
.valide("turn_right");
295 _LastFrameLeftButtonDown
= EventsListener
.isMouseButtonDown(leftButton
);
296 _LastFrameMousePosX
= EventsListener
.getMousePosX();
297 _LastFrameMousePosY
= EventsListener
.getMousePosY();
300 // update the refinePos (for landscape refining...)
301 // In fly mode, take the view pos.
303 View
.refinePos(View
.viewPos());
304 // Else take the entity pos (for less update if 3rd personn)
306 View
.refinePos(UserEntity
->pos());
308 // update camera collision once per frame
309 View
.updateCameraCollision();
311 NLMISC::CCDBNodeLeaf
*node
= _UiVarMkMoveDB
? &*_UiVarMkMoveDB
312 : &*(_UiVarMkMoveDB
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MK_MOVE"));
313 node
->setValue32(autowalkState());
317 //-----------------------------------------------
318 // Acceleration helper
319 //-----------------------------------------------
320 void CUserControls::updateVelocity (float deltaTime
, float acceleration
, float brake
, float speedMax
, float &speed
)
322 speed
+= acceleration
* deltaTime
;
323 // No acclereration, brake
324 if (acceleration
== 0)
343 clamp (speed
, -speedMax
, speedMax
);
344 }// updateVelocity //
346 //-----------------------------------------------
347 // keyboardRotation :
348 // Manage keyboard rotation
349 //-----------------------------------------------
350 void CUserControls::keyboardRotationLR (bool left
, bool right
)
357 accel
+= ClientCfg
.RotAccel
;
358 _RotateUserLRVelocity
= std::max (_RotateUserLRVelocity
, ClientCfg
.RotKeySpeedMin
);
363 accel
-= ClientCfg
.RotAccel
;
364 _RotateUserLRVelocity
= std::min (_RotateUserLRVelocity
, -ClientCfg
.RotKeySpeedMin
);
366 updateVelocity (DT
, accel
, ClientCfg
.RotAccel
, ClientCfg
.RotKeySpeedMax
, _RotateUserLRVelocity
);
369 UserEntity
->rotate(DT
*_RotateUserLRVelocity
);
372 _RotateUserLRVelocity
= 0;
373 }// keyboardRotation //
375 //-----------------------------------------------
376 // keyboardRotationUD :
377 //-----------------------------------------------
378 void CUserControls::keyboardRotationUD (bool up
, bool down
)
385 accel
+= ClientCfg
.RotAccel
;
386 _RotateUserUDVelocity
= std::max (_RotateUserUDVelocity
, ClientCfg
.RotKeySpeedMin
);
391 accel
-= ClientCfg
.RotAccel
;
392 _RotateUserUDVelocity
= std::min (_RotateUserUDVelocity
, -ClientCfg
.RotKeySpeedMin
);
394 updateVelocity (DT
, accel
, ClientCfg
.RotAccel
, ClientCfg
.RotKeySpeedMax
, _RotateUserUDVelocity
);
396 UserEntity
->rotHeadVertically(DT
*_RotateUserUDVelocity
);
397 UserEntity
->stopForceHeadPitchInFollow();
400 _RotateUserUDVelocity
= 0;
401 }// keyboardRotationUD //
403 //-----------------------------------------------
404 // keyboardRotationCameraLR :
405 //-----------------------------------------------
406 void CUserControls::keyboardRotationCameraLR (bool left
, bool right
)
413 accel
+= ClientCfg
.RotAccel
;
414 _RotateCameraLRVelocity
= std::max (_RotateCameraLRVelocity
, ClientCfg
.RotKeySpeedMin
);
419 accel
-= ClientCfg
.RotAccel
;
420 _RotateCameraLRVelocity
= std::min (_RotateCameraLRVelocity
, -ClientCfg
.RotKeySpeedMin
);
422 updateVelocity (DT
, accel
, ClientCfg
.RotAccel
, ClientCfg
.RotKeySpeedMax
, _RotateCameraLRVelocity
);
425 appendCameraDeltaYaw(DT
*_RotateCameraLRVelocity
);
428 _RotateCameraLRVelocity
= 0;
431 //-----------------------------------------------
433 //-----------------------------------------------
434 void CUserControls::getMouseAngleMove(float &dx
, float &dy
)
439 // The mouse may still "StandardMove" ie through a CEventMouseMove
440 // This can happen because of the "Rotation Anti-Lag system" which
441 // start to rotate before the mouse is hid and message mode passed
442 // to updateFreeLookPos
444 // if the mouse position changed
445 if( EventsListener
.getMousePosX() != _LastFrameMousePosX
||
446 EventsListener
.getMousePosY() != _LastFrameMousePosY
)
448 // get the mouse movement delta
449 float dmpx
= EventsListener
.getMousePosX() - _LastFrameMousePosX
;
450 float dmpy
= EventsListener
.getMousePosY() - _LastFrameMousePosY
;
452 // simulate mickeys mode if there is a mouse device
453 dmpx
*= (float)Driver
->getWindowWidth();
454 dmpy
*= (float)Driver
->getWindowHeight();
456 // handle inverted mouse, if enabled
457 if (ClientCfg
.FreeLookInverted
) dmpy
= -dmpy
;
460 EventsListener
.updateFreeLookPos(dmpx
, dmpy
);
463 // If the mouse move on the axis X, with a CGDMouseMove
464 if (EventsListener
.isMouseAngleX())
465 dx
= -EventsListener
.getMouseAngleX();
467 // If the mouse move on the axis Y, with a CGDMouseMove
468 if (EventsListener
.isMouseAngleY())
469 dy
= EventsListener
.getMouseAngleY();
473 //-----------------------------------------------
475 // Manage a free look.
476 //-----------------------------------------------
477 void CUserControls::freeLook(bool fullMode
)
479 static bool leftButtonDownInFullMode
= false;
481 EventsListener
.enableMouseSmoothing(true);
482 // **** Mouse rotation => apply to user
484 getMouseAngleMove(dx
,dy
);
489 if( UserEntity
->canChangeFront() )
491 UserEntity
->rotate(dx
);
495 appendCameraDeltaYaw(dx
);
500 UserEntity
->rotHeadVertically(dy
);
501 UserEntity
->stopForceHeadPitchInFollow();
505 // **** Only in fullMode (longClick for instance)
508 _CurrentFrameFreeLookCalled
= true;
510 CInterfaceManager
*IM
= CInterfaceManager::getInstance ();
512 // FREE LOOK : Hide the cursor
513 // disable interface mouse handling.
514 CWidgetManager::getInstance()->enableMouseHandling(false);
515 // Get the cursor instance
516 CViewPointer
*cursor
= static_cast< CViewPointer
* >( CWidgetManager::getInstance()->getPointer() );
523 // **** special actions keys while in free look
524 if (isSwimming() || isRiding())
525 keyboardRotationLR (false, false);
527 keyboardRotationLR (Actions
.valide("strafe_left"), Actions
.valide("strafe_right"));
529 if(Actions
.valide("turn_left"))
530 _DirectionMove
|= left
;
532 if(Actions
.valide("turn_right"))
533 _DirectionMove
|= right
;
535 // **** Left mouse click while in freelook: forward
536 // NB: in commonMove() the case "rightButtonDown+leftButtonDown" is managed.
537 // but still important to test it here, in case of FreeLook mode (no right button down needed)
538 if(EventsListener
.isMouseButtonDown (leftButton
))
541 _DirectionMove
|= forward
;
542 _DirectionMove
&= ~backward
;
543 // Quit autowalk if first frame in this mode
544 if( !leftButtonDownInFullMode
)
545 _DirectionMove
&= ~autowalk
;
547 // Moving Break any Follow Mode
548 UserEntity
->disableFollow();
549 UserEntity
->moveTo(CLFECOMMON::INVALID_SLOT
, 0.0, CUserEntity::None
);
551 leftButtonDownInFullMode
= true;
555 leftButtonDownInFullMode
= false;
558 if( UserEntity
->canChangeFront() )
560 // **** reset delta camera
561 applyCameraDeltaYawToUser();
568 //-----------------------------------------------
570 // Manage the camera look.
571 //-----------------------------------------------
572 void CUserControls::cameraLook(bool fullMode
)
574 EventsListener
.enableMouseSmoothing(true);
575 // **** Mouse rotation => apply X to camera, Y to user
577 getMouseAngleMove(dx
,dy
);
581 appendCameraDeltaYaw(dx
);
582 // If the mouse move on the axis Y, cahnge the actual user pitch (not the delta camera)
585 UserEntity
->rotHeadVertically(dy
);
586 UserEntity
->stopForceHeadPitchInFollow();
590 // **** Only in fullMode (longClick for instance)
593 CInterfaceManager
*IM
= CInterfaceManager::getInstance ();
595 // CAMERA LOOK : Hide the cursor
596 // disable interface mouse handling.
597 CWidgetManager::getInstance()->enableMouseHandling(false);
598 // Get the cursor instance
599 CViewPointer
*cursor
= static_cast< CViewPointer
* >( CWidgetManager::getInstance()->getPointer() );
611 //-----------------------------------------------
613 // Manage some common actions.
614 // \todo GUIGUI : manage control before entities update, but view only after move
615 //-----------------------------------------------
616 void CUserControls::commonMove()
618 CInterfaceManager
*IM
= CInterfaceManager::getInstance ();
621 // RESET USER CAMERA YAW
622 testApplyCameraYawToUser();
626 CEventsListener::TWheelState wheelState
= EventsListener
.getWheelState(); // Done all the time, to reset the state
627 View
.changeCameraDist((wheelState
== CEventsListener::foreward
), (wheelState
== CEventsListener::backward
));
628 View
.changeCameraDist(Actions
.valide("camera_foreward"), Actions
.valide("camera_backward"));
630 View
.changeCameraHeight(Actions
.valide("camera_up"), Actions
.valide("camera_down"));
633 keyboardRotationUD(Actions
.valide("look_up"), Actions
.valide("look_down"));
637 if(Actions
.valide("forward") && !_NeedReleaseForward
)
640 _DirectionMove
|= forward
;
641 _DirectionMove
&= ~backward
;
644 if(!_LastFrameForward
)
646 // Start autowalk mode.
647 if(Actions
.valide("toggle_auto_walk"))
648 _DirectionMove
|= autowalk
;
649 // Leave autowalk mode.
651 _DirectionMove
&= ~autowalk
;
654 if( _NextForwardCancelMoveTo
)
656 _NextForwardCancelMoveTo
= false;
657 UserEntity
->moveTo(CLFECOMMON::INVALID_SLOT
, 0.0, CUserEntity::None
);
658 applyCameraDeltaYawToUser();
664 if(_LastFrameForward
)
665 if(!(_DirectionMove
& autowalk
))
666 _DirectionMove
&= ~forward
;
668 // since forward is released, forward is now enable again
669 if( !Actions
.valide("forward") && _NeedReleaseForward
)
671 _NeedReleaseForward
= false;
672 _NextForwardCancelMoveTo
= true;
678 if(Actions
.valide("backward"))
680 if( UserEntity
->mode()!=MBEHAV::MOUNT_SWIM
)
683 _DirectionMove
|= backward
;
684 _DirectionMove
&= ~forward
;
687 if(!_LastFrameBackward
)
689 // Start autowalk mode.
690 if(Actions
.valide("toggle_auto_walk"))
691 _DirectionMove
|= autowalk
;
692 // Leave autowalk mode.
694 _DirectionMove
&= ~autowalk
;
700 if(_LastFrameBackward
)
701 if(!(_DirectionMove
& autowalk
))
702 _DirectionMove
&= ~backward
;
705 // turn left or right will break the move-to, so forward is enable again here
706 if(Actions
.valide("turn_left") || Actions
.valide("turn_right"))
708 if( _NeedReleaseForward
)
710 _NeedReleaseForward
= false;
711 _NextForwardCancelMoveTo
= false;
712 // if free cam mode reset the view because move if target turned around camera may be
713 if( !ClientCfg
.AutomaticCamera
)
715 resetSmoothCameraDeltaYaw();
722 // Must be after forward and backward to know the autowalk direction
724 if(Actions
.valide("toggle_auto_walk"))
727 if(!_LastFrameAutowalk
)
729 // Leave autowalk if forward and backward not pushed and only if autowalk just pushed.
730 if((_DirectionMove
& autowalk
) && !Actions
.valide("forward") && !Actions
.valide("backward"))
731 _DirectionMove
&= ~(autowalk
|forward
|backward
);
736 _DirectionMove
|= autowalk
;
737 // If not backward, default is forward.
738 if(!(_DirectionMove
& backward
))
739 _DirectionMove
|= forward
;
749 // Left Click and Dbl Click
750 bool dblClickLeft
= false;
751 if(EventsListener
.isMouseButtonPushed(leftButton
))
753 _LeftClickStart
= T1
;
755 if( EventsListener
.isMouseButtonReleased (leftButton
) )
757 if(T1
<= _LeftClickEnd
+ CWidgetManager::getInstance()->getUserDblClickDelay())
764 // Right Click and Dbl Click
765 bool dblClickRight
= false;
766 if(EventsListener
.isMouseButtonPushed(rightButton
))
768 _RightClickStart
= T1
;
770 if( EventsListener
.isMouseButtonReleased (rightButton
) )
772 if(T1
<= _RightClickEnd
+ CWidgetManager::getInstance()->getUserDblClickDelay())
774 dblClickRight
= true;
779 _CurrentFrameFreeLookCalled
= false;
782 if(EventsListener
.isMouseButtonReleased (rightButton
))
784 // stop FreeLook (and restore mouse/cursor)
789 // if we are in follow mode, do a cameraLook instead
790 if(UserEntity
->follow() || UserEntity
->moveTo())
800 // if rightbutton release while left MouseButton UP
801 if ( EventsListener
.isMouseButtonReleased (rightButton
) && EventsListener
.isMouseButtonUp (leftButton
))
807 CViewPointer
*cursor
= static_cast< CViewPointer
* >( CWidgetManager::getInstance()->getPointer() );
809 cursor
->getPointerPos(x
, y
);
812 CViewRenderer::getInstance()->getScreenSize(w
, h
);
813 // Get the pointer position (in float)
815 cursX
= (float)x
/(float)w
;
816 cursY
= (float)y
/(float)h
;
819 // Short Right Click -> Check Action
820 if ((T1
-_RightClickStart
) <= _TimeLongClick
)
824 CShapeInstanceReference instref
= EntitiesMngr
.getShapeInstanceUnderPos(cursX
, cursY
, instance_idx
);
825 nlinfo("instance_idx = %d", instance_idx
);
826 if (instance_idx
!= -1 && !instref
.Instance
.empty() && !instref
.ContextURL
.empty())
828 UserEntity
->selection(CLFECOMMON::INVALID_SLOT
);
831 if (ClientCfg
.SelectWithRClick
|| R2::isEditionCurrent())
833 // nb : the ring editor also need that kind of events
834 execActionCursorPos(true,dblClickRight
);
837 // Launch Context Menu
838 if (R2::getEditor().getMode() != R2::CEditor::EditionMode
)
839 IM
->launchContextMenuInGame("ui:interface:game_context_menu");
843 // Give back the mouse handling to the interface.
844 CWidgetManager::getInstance()->enableMouseHandling(true);
845 EventsListener
.enableMouseSmoothing(false);
848 // if leftbutton release while right MouseButton UP
849 if ( EventsListener
.isMouseButtonReleased (leftButton
) && EventsListener
.isMouseButtonUp (rightButton
))
854 // Short Left Click -> Check Action
855 if((T1
-_LeftClickStart
) <= _TimeLongClick
)
857 execActionCursorPos(false, dblClickLeft
);
860 // Give back the mouse handling to the interface.
861 CWidgetManager::getInstance()->enableMouseHandling(true);
862 EventsListener
.enableMouseSmoothing(false);
866 // if Right button down
867 if (EventsListener
.isMouseButtonDown (rightButton
))
869 // NB: start the freeLook sooner than a longclick
870 if((T1
-_RightClickStart
) > _TimeBeforeMouseSlide
)
872 // if we are in follow mode, do a cameraLook on RightSlide, else do a freeLook
873 if(UserEntity
->follow() || UserEntity
->moveTo() || UserEntity
->isSit() || UserEntity
->isAFK())
874 // FullMode (hide mouse...) only if longClick
875 cameraLook(T1
-_RightClickStart
> _TimeLongClick
);
878 // FullMode (hide mouse...) only if longClick
879 freeLook(T1
-_RightClickStart
> _TimeLongClick
);
881 if( _NeedReleaseForward
)
883 _NeedReleaseForward
= false;
884 _NextForwardCancelMoveTo
= false;
885 // if free cam mode reset the view because move if target turned around camera may be
886 if( !ClientCfg
.AutomaticCamera
)
888 resetSmoothCameraDeltaYaw();
894 // if Right Mouse button is up
897 // mouse camera look: when the user hold down the left button for a time, while the right button is up
898 if (EventsListener
.isMouseButtonDown (leftButton
))
900 // NB: start the freeLook sooner than a longclick
901 if((T1
-_LeftClickStart
) > _TimeBeforeMouseSlide
)
902 // FullMode (hide mouse...) only if longClick
903 cameraLook(T1
-_LeftClickStart
> _TimeLongClick
);
906 if ( ! (isSwimming() || isRiding()))
909 if(Actions
.valide("strafe_left"))
910 _DirectionMove
|= left
;
912 if(Actions
.valide("strafe_right"))
913 _DirectionMove
|= right
;
916 if( !UserEntity
->isSit() && !UserEntity
->isAFK() )
918 // Test rotation keys
919 if( UserEntity
->canChangeFront() )
921 keyboardRotationLR (Actions
.valide("turn_left"), Actions
.valide("turn_right"));
925 keyboardRotationCameraLR (Actions
.valide("turn_left"), Actions
.valide("turn_right"));
934 // If both button are pressed in any case (whatever the _TimeBeforeMouseSlide time), treat as "forward"
935 static bool bothButtonPressed
= false;
936 if(EventsListener
.isMouseButtonDown (leftButton
) && EventsListener
.isMouseButtonDown (rightButton
))
939 _DirectionMove
|= forward
;
940 _DirectionMove
&= ~backward
;
941 // quit autowalk if entering both button pressed mode
942 if( !bothButtonPressed
)
944 _DirectionMove
&= ~autowalk
;
947 // Moving Break any Follow Mode
948 UserEntity
->disableFollow();
949 UserEntity
->moveTo(CLFECOMMON::INVALID_SLOT
, 0.0, CUserEntity::None
);
952 UserEntity
->sit(false);
953 // and no more in afk mode
954 UserEntity
->setAFK(false);
956 bothButtonPressed
= true;
960 bothButtonPressed
= false;
965 // Manage here the Release of Forward in any of third case (keyUP, leftButton in freeLook, and both buttons down)
966 if( (_DirectionMove
& forward
) && (_DirectionMove
& autowalk
)==0)
968 // freeLook() called and leftButton down => walk
969 bool walkInFreeLook
= _CurrentFrameFreeLookCalled
&& EventsListener
.isMouseButtonDown(leftButton
);
970 // both button down => walk too
971 bool walkWithBothButton
= (EventsListener
.isMouseButtonDown (leftButton
) && EventsListener
.isMouseButtonDown (rightButton
));
972 // if no forward action valid, quit forward
973 if(! (Actions
.valide("forward") || walkInFreeLook
|| walkWithBothButton
) )
974 _DirectionMove
&= ~forward
;
979 // CAMERA DELTA YAW ADDS
983 // reset too if middle button clicked
984 if(EventsListener
.isMouseButtonReleased(middleButton
))
986 resetSmoothCameraDeltaYaw();
989 // Handle rotations with keys
990 bool cameraLeft
,cameraRight
;
991 if( UserEntity
->isSit() || UserEntity
->isAFK() )
993 cameraLeft
= Actions
.valide("camera_turn_left") || Actions
.valide("turn_left");
994 cameraRight
= Actions
.valide("camera_turn_right") || Actions
.valide("turn_right");
998 cameraLeft
= Actions
.valide("camera_turn_left");
999 cameraRight
= Actions
.valide("camera_turn_right");
1001 keyboardRotationCameraLR (cameraLeft
, cameraRight
);
1005 if(_ResetSmoothCameraDeltaYaw
!=ResetCDYOff
)
1007 // normalize in -Pi/Pi
1008 _UserCameraDeltaYaw
= float(fmod(_UserCameraDeltaYaw
, 2.0f
*(float)Pi
));
1009 if(_UserCameraDeltaYaw
>Pi
)
1010 _UserCameraDeltaYaw
-= 2*float(Pi
);
1011 else if(_UserCameraDeltaYaw
<-Pi
)
1012 _UserCameraDeltaYaw
+= 2*float(Pi
);
1015 if(_UserCameraDeltaYaw
<0)
1017 _UserCameraDeltaYaw
+= DT
*ClientCfg
.CameraResetSpeed
;
1018 if(_UserCameraDeltaYaw
>=0)
1020 _UserCameraDeltaYaw
= 0;
1021 _ResetSmoothCameraDeltaYaw
= ResetCDYOff
;
1026 _UserCameraDeltaYaw
-= DT
*ClientCfg
.CameraResetSpeed
;
1027 if(_UserCameraDeltaYaw
<=0)
1029 _UserCameraDeltaYaw
= 0;
1030 _ResetSmoothCameraDeltaYaw
= ResetCDYOff
;
1036 ////////////////////
1038 ////////////////////
1042 //-----------------------------------------------
1044 // Move the caracter according to the inputs.
1045 //-----------------------------------------------
1046 void CUserControls::move()
1048 // If the user is sit(), remove any move
1049 if( UserEntity
->isSit() || UserEntity
->isAFK() )
1050 _DirectionMove
= none
;
1052 if( _DirectionMove
!= none
)
1054 cancelActionsWhenMoving();
1057 // Forward/backward motion.
1058 float direction
= 0;
1059 if(_DirectionMove
&forward
)
1061 if( UserEntity
->mode() != MBEHAV::MOUNT_SWIM
)
1063 if(_DirectionMove
&backward
)
1066 // Changes the front velocity for the user.
1067 UserEntity
->frontVelocity(direction
);
1070 float directionStrafe
= 0;
1071 if( ! (isSwimming() || isRiding()) )
1073 if(_DirectionMove
&left
)
1074 directionStrafe
+= 1;
1075 if(_DirectionMove
&right
)
1076 directionStrafe
-= 1;
1078 else if ( isRiding() )
1080 // Check if the mount is able to run, and force walking mode if not, because the player can always switch the mode
1081 UserEntity
->checkMountAbleToRun();
1084 // Changes the lateral velocity for the user.
1085 UserEntity
->lateralVelocity(directionStrafe
);
1090 //-----------------------------------------------
1092 // Change the current Mode.
1093 //-----------------------------------------------
1094 void CUserControls::mode(const TMoveMode mode
)
1096 // Unlock the motion;
1099 // If the mode didn't change -> return.
1103 // Write that the last Mode end.
1107 interfaceModeStop();
1124 // Third Person View Mode
1133 // Backup the last Mode.
1135 // Set the new mode.
1138 // Write that the new Mode Start.
1142 interfaceModeStart();
1160 // Third Person View Mode
1170 //-----------------------------------------------
1172 // Return the string associated to the motion Mode.
1173 //-----------------------------------------------
1174 string
CUserControls::modeStr() const
1179 case CUserControls::InterfaceMode
:
1180 return "InterfaceMode";
1183 case CUserControls::AIMode
:
1187 case CUserControls::DeathMode
:
1191 case CUserControls::MountMode
:
1194 // Third Person View Mode
1195 case CUserControls::ThirdMode
:
1196 return "Third Person View Mode";
1200 return "Unknown Control Mode";
1204 //-----------------------------------------------
1206 //-----------------------------------------------
1207 // execActionCursorPos :
1208 // Execute action depending on the cursor position (left/right click).
1209 //-----------------------------------------------
1210 void CUserControls::execActionCursorPos(bool rightClick
, bool dblClick
)
1212 // Check there is no interface under the cursor.
1213 if( CWidgetManager::getInstance()->isMouseOverWindow())
1215 // Update the cursor.
1218 ContextCur
.execute(rightClick
,dblClick
);
1219 }// execActionCursorPos //
1222 //-----------------------------------------------
1223 // resetCameraDeltaYaw()
1224 //-----------------------------------------------
1225 void CUserControls::resetCameraDeltaYaw()
1227 _UserCameraDeltaYaw
= 0.f
;
1228 _ResetSmoothCameraDeltaYaw
= ResetCDYOff
;
1232 //-----------------------------------------------
1233 // appendCameraDeltaYaw()
1234 //-----------------------------------------------
1235 void CUserControls::appendCameraDeltaYaw(float dYaw
)
1237 _UserCameraDeltaYaw
+= dYaw
;
1239 // Stop the smooth reset if any
1240 _ResetSmoothCameraDeltaYaw
= ResetCDYOff
;
1244 //-----------------------------------------------
1245 // resetSmoothCameraDeltaYaw()
1246 //-----------------------------------------------
1247 void CUserControls::resetSmoothCameraDeltaYaw()
1249 // Force the reset if the user currently in follow/moveTo
1250 if(UserEntity
->follow() || UserEntity
->moveTo())
1251 _ResetSmoothCameraDeltaYaw
= ResetCDYForced
;
1253 _ResetSmoothCameraDeltaYaw
= ResetCDYOn
;
1257 //-----------------------------------------------
1258 // applyCameraDeltaYawToUser();
1259 //-----------------------------------------------
1260 void CUserControls::applyCameraDeltaYawToUser()
1262 // apply delta camera to the UserEntity
1263 UserEntity
->rotate(_UserCameraDeltaYaw
);
1265 _UserCameraDeltaYaw
= 0.f
;
1266 _ResetSmoothCameraDeltaYaw
= ResetCDYOff
;
1270 //-----------------------------------------------
1271 // testApplyCameraYawToUser()
1272 //-----------------------------------------------
1273 void CUserControls::testApplyCameraYawToUser()
1275 // only if not in "camera look" mode
1276 if(!EventsListener
.isMouseButtonDown(leftButton
))
1278 // if any of those actions start
1279 if( ( !_LastFrameForward
&& Actions
.valide("forward") && !_NeedReleaseForward
) ||
1280 ( !_LastFrameBackward
&& Actions
.valide("backward") ) ||
1281 ( !_LastFrameAutowalk
&& Actions
.valide("toggle_auto_walk") ) )
1282 /*( !_LastFrameStrafeLeft && Actions.valide("strafe_left") ) ||
1283 ( !_LastFrameStrafeRight && Actions.valide("strafe_right") ) ||
1284 ( !_LastFrameTurnLeft && Actions.valide("turn_left") ) ||
1285 ( !_LastFrameTurnRight && Actions.valide("turn_right") ) )*/
1287 applyCameraDeltaYawToUser();
1291 // if both buttons are pressed, then reset.
1292 // This is for the case where right button is pressed while left button was down for cameraLook()
1293 if( EventsListener
.isMouseButtonDown(leftButton
) && EventsListener
.isMouseButtonDown(rightButton
))
1295 applyCameraDeltaYawToUser();
1301 //-----------------------------------------------
1303 //-----------------------------------------------
1304 void CUserControls::commonSetView()
1306 // Set the view direction.
1309 camMat
.setRot(CVector(0,-1,0), CVector(1,0,0), CVector(0,0,1), true);
1310 camMat
.rotateZ(UserEntity
->frontYaw() + _UserCameraDeltaYaw
);
1311 camMat
.rotateX(float(UserEntity
->getHeadPitch()));
1312 View
.view(camMat
.getJ());
1314 // Update the mount direction.
1315 CEntityCL
*mount
= EntitiesMngr
.entity(UserEntity
->parent());
1318 mount
->front(UserEntity
->front());
1322 //-----------------------------------------------
1324 //-----------------------------------------------
1325 void CUserControls::startFreeLook()
1330 //-----------------------------------------------
1332 //-----------------------------------------------
1333 void CUserControls::stopFreeLook()
1335 EventsListener
.enableMouseSmoothing(false);
1340 // Give back the mouse handling to the interface.
1341 CWidgetManager::getInstance()->enableMouseHandling(true);
1345 //-----------------------------------------------
1346 // cancelActionsWhenMoving()
1347 //-----------------------------------------------
1348 void CUserControls::cancelActionsWhenMoving()
1350 if( UserEntity
->behaviour() == MBEHAV::EXTRACTING
||
1351 (UserEntity
->behaviour() >= MBEHAV::MAGIC_CASTING_BEHAVIOUR_BEGIN
&& UserEntity
->behaviour() <= MBEHAV::MAGIC_CASTING_BEHAVIOUR_END
) )
1353 UserEntity
->cancelAllPhrases();
1355 if( UserEntity
->behaviour() == MBEHAV::RANGE_ATTACK
)
1357 //UserEntity->disengage();
1361 //-----------------------------------------------
1362 // checkSpeedFactor()
1363 //-----------------------------------------------
1364 void CUserControls::checkSpeedFactor()
1366 if (!IngameDbMngr
.initInProgress())
1368 if (UserEntity
->isSit())
1371 // check if speed factor is zero, and if yes, notify the player
1372 CCDBNodeLeaf
*pNodeLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:SPEED_FACTOR", false);
1373 if (pNodeLeaf
&& pNodeLeaf
->getValue64() == 0) {
1374 CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiSpeedFactorZero"), "CHK");