Merge branch '164-crash-on-patching-and-possibly-right-after-login' into main/gingo...
[ryzomcore.git] / ryzom / client / src / motion / user_controls.cpp
blob632fbb5bef824e2600a38574f37bf92bfa23bfd9
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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>
8 //
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/>.
24 #include "stdpch.h"
27 //////////////
28 // Includes //
29 //////////////
30 // GAME SHARE
31 #include "game_share/bot_chat_types.h"
32 // Client.
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"
41 #include "../view.h"
42 #include "../input.h"
44 #include "../r2/editor.h"
46 #ifdef DEBUG_NEW
47 #define new DEBUG_NEW
48 #endif
50 ///////////
51 // Using //
52 ///////////
53 using namespace std;
54 using namespace NLMISC;
55 using namespace NL3D;
58 /////////////
59 // Externs //
60 /////////////
61 extern UDriver *Driver;
62 extern UScene *Scene;
63 extern CEventsListener EventsListener; // Inputs Manager
65 /////////////
66 // Globals //
67 /////////////
68 // User Controls (mouse, keyboard, interfaces, ...)
69 CUserControls UserControls;
71 // Hierarchical timer
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);
80 else
81 return false;
84 static bool isSit()
86 if (UserEntity)
87 return UserEntity->isSit();
88 else
89 return false;
92 static bool isRiding()
94 if (UserEntity)
95 return UserEntity->isRiding();
96 else
97 return false;
101 ///////////////
102 // Functions //
103 ///////////////
104 //---------------------------------------------------
105 // CUserControls :
106 // Constructor.
107 //---------------------------------------------------
108 CUserControls::CUserControls()
110 init();
111 }// CUserControls //
113 //---------------------------------------------------
114 // init :
115 // Initialize all the components.
116 //---------------------------------------------------
117 void CUserControls::init()
119 // Default Mode is Interface Mode.
120 _LastMode = _Mode = InterfaceMode;
122 _LeftClickStart = 0;
123 _LeftClickEnd = 0;
124 _RightClickStart = 0;
125 _RightClickEnd = 0;
126 _TimeBeforeMouseSlide = 50;
127 _TimeLongClick = 200;
129 _TransSpeed = 1.f;
131 _UpdateView = false;
132 _ZOscil = 0;
133 _Acc = 0;
134 _T0 = 0;
135 _T = 0;
136 _V0 = _TransSpeed;
138 _T0View = 0;
139 _TView = 0;
141 _TurnBack = false;
142 _ClickMove = false;
144 _Start = CVector(0,0,0);
145 _Destination = _Start;
147 _Dist = -1;
149 _DirectionMove = none;
151 _Locked = false; // Move is not locked.
153 _FreeLook = false;
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;
168 _CameraAuto = false;
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;
184 }// init //
186 void CUserControls::reset()
188 init();
191 //-----------------------------------------------
192 // needReleaseForward :
193 //-----------------------------------------------
194 void CUserControls::needReleaseForward()
196 if( Actions.valide("forward") )
198 _NeedReleaseForward = true;
203 //-----------------------------------------------
204 // autowalkState :
205 //-----------------------------------------------
206 void CUserControls::autowalkState(bool enable)
208 if(enable)
210 checkSpeedFactor();
211 _DirectionMove |= autowalk;
212 // If not backward, default is forward.
213 if(!(_DirectionMove & backward))
214 _DirectionMove |= forward;
216 else
217 _DirectionMove &= ~(autowalk|forward|backward);
218 }// autowalkState //
221 //-----------------------------------------------
222 // update :
223 // Main function of the Class -> Call it each frame.
224 //-----------------------------------------------
225 void CUserControls::update()
227 H_AUTO_USE ( RZ_Client_User_Controls_Update );
229 View.update();
231 // Reset the moving direction.
232 _DirectionMove &= ~(left | right);
234 // if not locked, move
235 if(!_Locked)
237 // What is the current _Mode ?
238 switch(_Mode)
240 // Interface Mode.
241 case InterfaceMode:
242 interfaceMode();
243 break;
245 // AI Mode
246 case AIMode:
247 aiMode();
248 break;
250 // Death Mode
251 case DeathMode:
252 deathMode();
253 break;
255 // Mount Mode
256 case MountMode:
257 mountMode();
258 break;
260 // Third Person View Mode
261 case ThirdMode:
262 thirdMode();
263 break;
265 default:
266 break;
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;
288 else
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.
302 if(_Mode == AIMode)
303 View.refinePos(View.viewPos());
304 // Else take the entity pos (for less update if 3rd personn)
305 else
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());
314 }// update //
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)
326 brake *= deltaTime;
327 if (speed < 0)
329 if (speed > -brake)
330 speed = 0;
331 else
332 speed += brake;
334 else
336 if (speed < brake)
337 speed = 0;
338 else
339 speed -= brake;
342 // Clamp the speed
343 clamp (speed, -speedMax, speedMax);
344 }// updateVelocity //
346 //-----------------------------------------------
347 // keyboardRotation :
348 // Manage keyboard rotation
349 //-----------------------------------------------
350 void CUserControls::keyboardRotationLR (bool left, bool right)
352 if (left || right)
354 float accel = 0;
355 if (left)
357 accel += ClientCfg.RotAccel;
358 _RotateUserLRVelocity = std::max (_RotateUserLRVelocity, ClientCfg.RotKeySpeedMin);
361 if (right)
363 accel -= ClientCfg.RotAccel;
364 _RotateUserLRVelocity = std::min (_RotateUserLRVelocity, -ClientCfg.RotKeySpeedMin);
366 updateVelocity (DT, accel, ClientCfg.RotAccel, ClientCfg.RotKeySpeedMax, _RotateUserLRVelocity);
368 // Rotate the body.
369 UserEntity->rotate(DT*_RotateUserLRVelocity);
371 else
372 _RotateUserLRVelocity = 0;
373 }// keyboardRotation //
375 //-----------------------------------------------
376 // keyboardRotationUD :
377 //-----------------------------------------------
378 void CUserControls::keyboardRotationUD (bool up, bool down)
380 if (up || down)
382 float accel = 0;
383 if (up)
385 accel += ClientCfg.RotAccel;
386 _RotateUserUDVelocity = std::max (_RotateUserUDVelocity, ClientCfg.RotKeySpeedMin);
389 if (down)
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();
399 else
400 _RotateUserUDVelocity = 0;
401 }// keyboardRotationUD //
403 //-----------------------------------------------
404 // keyboardRotationCameraLR :
405 //-----------------------------------------------
406 void CUserControls::keyboardRotationCameraLR (bool left, bool right)
408 if (left || right)
410 float accel = 0;
411 if (left)
413 accel += ClientCfg.RotAccel;
414 _RotateCameraLRVelocity = std::max (_RotateCameraLRVelocity, ClientCfg.RotKeySpeedMin);
417 if (right)
419 accel -= ClientCfg.RotAccel;
420 _RotateCameraLRVelocity = std::min (_RotateCameraLRVelocity, -ClientCfg.RotKeySpeedMin);
422 updateVelocity (DT, accel, ClientCfg.RotAccel, ClientCfg.RotKeySpeedMax, _RotateCameraLRVelocity);
424 // Rotate the camera
425 appendCameraDeltaYaw(DT*_RotateCameraLRVelocity);
427 else
428 _RotateCameraLRVelocity = 0;
431 //-----------------------------------------------
432 // getMouseAngleMove
433 //-----------------------------------------------
434 void CUserControls::getMouseAngleMove(float &dx, float &dy)
436 dx = 0.0f;
437 dy = 0.0f;
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;
459 // update free look
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 //-----------------------------------------------
474 // freeLook :
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
483 float dx,dy;
484 getMouseAngleMove(dx,dy);
486 // apply
487 if(dx != 0.f)
489 if( UserEntity->canChangeFront() )
491 UserEntity->rotate(dx);
493 else
495 appendCameraDeltaYaw(dx);
498 if(dy != 0.f)
500 UserEntity->rotHeadVertically(dy);
501 UserEntity->stopForceHeadPitchInFollow();
505 // **** Only in fullMode (longClick for instance)
506 if(fullMode)
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() );
517 if(cursor)
519 // Hide the Cursor.
520 SetMouseFreeLook();
523 // **** special actions keys while in free look
524 if (isSwimming() || isRiding())
525 keyboardRotationLR (false, false);
526 else
527 keyboardRotationLR (Actions.valide("strafe_left"), Actions.valide("strafe_right"));
528 // Strafe Left
529 if(Actions.valide("turn_left"))
530 _DirectionMove |= left;
531 // Strafe Right
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))
540 // Forward.
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;
553 else
555 leftButtonDownInFullMode = false;
558 if( UserEntity->canChangeFront() )
560 // **** reset delta camera
561 applyCameraDeltaYawToUser();
565 }// freeLook //
568 //-----------------------------------------------
569 // cameraLook :
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
576 float dx,dy;
577 getMouseAngleMove(dx,dy);
579 // apply
580 if(dx != 0.f)
581 appendCameraDeltaYaw(dx);
582 // If the mouse move on the axis Y, cahnge the actual user pitch (not the delta camera)
583 if(dy != 0.f)
585 UserEntity->rotHeadVertically(dy);
586 UserEntity->stopForceHeadPitchInFollow();
590 // **** Only in fullMode (longClick for instance)
591 if(fullMode)
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() );
600 if(cursor)
602 // Hide the Cursor.
603 SetMouseFreeLook();
608 }// cameraLook //
611 //-----------------------------------------------
612 // commonMove :
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 ();
620 /////////////////
621 // RESET USER CAMERA YAW
622 testApplyCameraYawToUser();
624 /////////////////
625 // MOUSE WHEEL //
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"));
629 // Camera Up/Down.
630 View.changeCameraHeight(Actions.valide("camera_up"), Actions.valide("camera_down"));
631 //////////////////
632 // LOOK UP/DOWN //
633 keyboardRotationUD(Actions.valide("look_up"), Actions.valide("look_down"));
634 /////////////
635 // FORWARD //
636 // ON
637 if(Actions.valide("forward") && !_NeedReleaseForward)
639 // Forward
640 _DirectionMove |= forward;
641 _DirectionMove &= ~backward;
643 // Start Action
644 if(!_LastFrameForward)
646 // Start autowalk mode.
647 if(Actions.valide("toggle_auto_walk"))
648 _DirectionMove |= autowalk;
649 // Leave autowalk mode.
650 else
651 _DirectionMove &= ~autowalk;
654 if( _NextForwardCancelMoveTo )
656 _NextForwardCancelMoveTo = false;
657 UserEntity->moveTo(CLFECOMMON::INVALID_SLOT, 0.0, CUserEntity::None);
658 applyCameraDeltaYawToUser();
661 // OFF
662 else
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;
675 //////////////
676 // BACKWARD //
677 // ON
678 if(Actions.valide("backward"))
680 if( UserEntity->mode()!=MBEHAV::MOUNT_SWIM )
682 // Backward
683 _DirectionMove |= backward;
684 _DirectionMove &= ~forward;
686 // Start Action
687 if(!_LastFrameBackward)
689 // Start autowalk mode.
690 if(Actions.valide("toggle_auto_walk"))
691 _DirectionMove |= autowalk;
692 // Leave autowalk mode.
693 else
694 _DirectionMove &= ~autowalk;
697 // OFF
698 else
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();
720 //////////////
721 // AUTOWALK //
722 // Must be after forward and backward to know the autowalk direction
723 // ON
724 if(Actions.valide("toggle_auto_walk"))
726 // Action start
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);
732 else
734 checkSpeedFactor();
735 // Start Autowalk
736 _DirectionMove |= autowalk;
737 // If not backward, default is forward.
738 if(!(_DirectionMove & backward))
739 _DirectionMove |= forward;
745 //////////////
746 // MOUSE MANAGEMENT
747 //////////////
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())
759 dblClickLeft = true;
761 _LeftClickEnd = T1;
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;
776 _RightClickEnd = T1;
779 _CurrentFrameFreeLookCalled= false;
780 if(_FreeLook)
782 if(EventsListener.isMouseButtonReleased (rightButton))
784 // stop FreeLook (and restore mouse/cursor)
785 stopFreeLook();
787 else
789 // if we are in follow mode, do a cameraLook instead
790 if(UserEntity->follow() || UserEntity->moveTo())
791 cameraLook(true);
792 else
793 freeLook(true);
796 else
798 if (!_MouseCaptured)
800 // if rightbutton release while left MouseButton UP
801 if ( EventsListener.isMouseButtonReleased (rightButton) && EventsListener.isMouseButtonUp (leftButton))
803 // Cursor mode.
804 SetMouseCursor ();
806 sint32 x, y = -1;
807 CViewPointer *cursor = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
808 if (cursor)
809 cursor->getPointerPos(x, y);
811 uint32 w, h;
812 CViewRenderer::getInstance()->getScreenSize(w, h);
813 // Get the pointer position (in float)
814 float cursX, cursY;
815 cursX = (float)x/(float)w;
816 cursY = (float)y/(float)h;
819 // Short Right Click -> Check Action
820 if ((T1-_RightClickStart) <= _TimeLongClick)
823 sint32 instance_idx;
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))
851 // Cursor mode.
852 SetMouseCursor ();
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);
876 else
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
895 else
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()))
908 // Strafe Left
909 if(Actions.valide("strafe_left"))
910 _DirectionMove |= left;
911 // Strafe Right
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"));
923 else
925 keyboardRotationCameraLR (Actions.valide("turn_left"), Actions.valide("turn_right"));
932 if (!_MouseCaptured)
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))
938 // Forward.
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);
951 // if sit, stand up
952 UserEntity->sit(false);
953 // and no more in afk mode
954 UserEntity->setAFK(false);
956 bothButtonPressed = true;
958 else
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;
978 ////////////////////
979 // CAMERA DELTA YAW ADDS
980 ////////////////////
981 if (!_MouseCaptured)
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");
996 else
998 cameraLeft = Actions.valide("camera_turn_left");
999 cameraRight = Actions.valide("camera_turn_right");
1001 keyboardRotationCameraLR (cameraLeft, cameraRight);
1004 // reset over time
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);
1014 // reset over time
1015 if(_UserCameraDeltaYaw<0)
1017 _UserCameraDeltaYaw+= DT*ClientCfg.CameraResetSpeed;
1018 if(_UserCameraDeltaYaw>=0)
1020 _UserCameraDeltaYaw= 0;
1021 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1024 else
1026 _UserCameraDeltaYaw-= DT*ClientCfg.CameraResetSpeed;
1027 if(_UserCameraDeltaYaw<=0)
1029 _UserCameraDeltaYaw= 0;
1030 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1036 ////////////////////
1037 // APPLY MOTION.
1038 ////////////////////
1039 move();
1040 }// commonMove //
1042 //-----------------------------------------------
1043 // move :
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)
1060 direction += 1;
1061 if( UserEntity->mode() != MBEHAV::MOUNT_SWIM )
1063 if(_DirectionMove&backward)
1064 direction -= 1;
1066 // Changes the front velocity for the user.
1067 UserEntity->frontVelocity(direction);
1069 // Strafe motion.
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);
1087 }// move //
1090 //-----------------------------------------------
1091 // mode :
1092 // Change the current Mode.
1093 //-----------------------------------------------
1094 void CUserControls::mode(const TMoveMode mode)
1096 // Unlock the motion;
1097 _Locked = false;
1099 // If the mode didn't change -> return.
1100 if(_Mode == mode)
1101 return;
1103 // Write that the last Mode end.
1104 switch(_Mode)
1106 case InterfaceMode:
1107 interfaceModeStop();
1108 break;
1110 case AIMode:
1111 aiModeStop();
1112 break;
1114 // Death Mode
1115 case DeathMode:
1116 deathModeStop();
1117 break;
1119 // Mount Mode
1120 case MountMode:
1121 mountModeStop();
1122 break;
1124 // Third Person View Mode
1125 case ThirdMode:
1126 thirdModeStop();
1127 break;
1129 default:
1130 break;
1133 // Backup the last Mode.
1134 _LastMode = _Mode;
1135 // Set the new mode.
1136 _Mode = mode;
1138 // Write that the new Mode Start.
1139 switch(_Mode)
1141 case InterfaceMode:
1142 interfaceModeStart();
1143 break;
1145 // AI Mode
1146 case AIMode:
1147 aiModeStart();
1148 break;
1150 // Death Mode
1151 case DeathMode:
1152 deathModeStart();
1153 break;
1155 // Mount Mode
1156 case MountMode:
1157 mountModeStart();
1158 break;
1160 // Third Person View Mode
1161 case ThirdMode:
1162 thirdModeStart();
1163 break;
1165 default:
1166 break;
1168 }// mode //
1170 //-----------------------------------------------
1171 // modeStr :
1172 // Return the string associated to the motion Mode.
1173 //-----------------------------------------------
1174 string CUserControls::modeStr() const
1176 switch(mode())
1178 // Interface Mode
1179 case CUserControls::InterfaceMode:
1180 return "InterfaceMode";
1182 // Camera Mode
1183 case CUserControls::AIMode:
1184 return "AIMode";
1186 // Death Mode
1187 case CUserControls::DeathMode:
1188 return "DeathMode";
1190 // Mount Mode
1191 case CUserControls::MountMode:
1192 return "MountMode";
1194 // Third Person View Mode
1195 case CUserControls::ThirdMode:
1196 return "Third Person View Mode";
1198 // Unknown Mode
1199 default:
1200 return "Unknown Control Mode";
1202 }// modeStr //
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())
1214 return;
1215 // Update the cursor.
1216 ContextCur.check();
1217 // Execute Action.
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;
1252 else
1253 _ResetSmoothCameraDeltaYaw= ResetCDYOn;
1257 //-----------------------------------------------
1258 // applyCameraDeltaYawToUser();
1259 //-----------------------------------------------
1260 void CUserControls::applyCameraDeltaYawToUser()
1262 // apply delta camera to the UserEntity
1263 UserEntity->rotate(_UserCameraDeltaYaw);
1264 // and reset
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 //-----------------------------------------------
1302 //commonSetView()
1303 //-----------------------------------------------
1304 void CUserControls::commonSetView()
1306 // Set the view direction.
1307 CMatrix camMat;
1308 camMat.identity();
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());
1316 if(mount)
1318 mount->front(UserEntity->front());
1322 //-----------------------------------------------
1323 // startFreeLook()
1324 //-----------------------------------------------
1325 void CUserControls::startFreeLook()
1327 _FreeLook= true;
1330 //-----------------------------------------------
1331 // stopFreeLook()
1332 //-----------------------------------------------
1333 void CUserControls::stopFreeLook()
1335 EventsListener.enableMouseSmoothing(false);
1336 _FreeLook= false;
1338 // Cursor mode
1339 SetMouseCursor ();
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())
1369 return;
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");