1 #include "Font_Control.h"
2 #include "Real_Time_Input.h"
3 #include "Soldier_Find.h"
4 #include "Turn_Based_Input.h"
5 #include "PathAI.h"
6 #include "Soldier_Control.h"
7 #include "Animation_Control.h"
8 #include "Animation_Data.h"
9 #include "Timer_Control.h"
10 #include "Handle_UI.h"
11 #include "Isometric_Utils.h"
12 #include "Input.h"
13 #include "Overhead.h"
14 #include "Interface.h"
15 #include "Cursor_Control.h"
16 #include "Points.h"
17 #include "Interactive_Tiles.h"
18 #include "Interface_Cursors.h"
19 #include "Environment.h"
20 #include "OppList.h"
21 #include "Spread_Burst.h"
22 #include "Overhead_Map.h"
23 #include "World_Items.h"
24 #include "Game_Clock.h"
25 #include "Interface_Items.h"
26 #include "UI_Cursors.h"
27 #include "StrategicMap.h"
28 #include "Soldier_Profile.h"
29 #include "Soldier_Create.h"
30 #include "Soldier_Add.h"
31 #include "Dialogue_Control.h"
32 #include "Interface_Dialogue.h"
33 #include "Tile_Animation.h"
34 #include "Merc_Entering.h"
35 #include "Explosion_Control.h"
36 #include "Message.h"
37 #include "Strategic_Exit_GUI.h"
38 #include "Assignments.h"
39 #include "Map_Screen_Interface.h"
40 #include "RenderWorld.h"
41 #include "GameSettings.h"
42 #include "English.h"
43 #include "Text.h"
44 #include "Soldier_Macros.h"
45 #include "Render_Dirty.h"
46
47 #include "ContentManager.h"
48 #include "GameInstance.h"
49 #include "policy/GamePolicy.h"
50
51 static BOOLEAN gfStartLookingForRubberBanding = FALSE;
52 static UINT16 gusRubberBandX = 0;
53 static UINT16 gusRubberBandY = 0;
54
55
56 BOOLEAN gfBeginBurstSpreadTracking = FALSE;
57
58 BOOLEAN gfRTClickLeftHoldIntercepted = FALSE;
59 static BOOLEAN gfRTHaveClickedRightWhileLeftDown = FALSE;
60
61
62 static void QueryRTLeftButton(UIEventKind* puiNewEvent);
63 static void QueryRTRightButton(UIEventKind* puiNewEvent);
64 static void QueryRTMiddleButton(UIEventKind* puiNewEvent);
65
66
GetRTMouseButtonInput(UIEventKind * puiNewEvent)67 void GetRTMouseButtonInput(UIEventKind* puiNewEvent)
68 {
69 QueryRTLeftButton( puiNewEvent );
70 QueryRTRightButton( puiNewEvent );
71 QueryRTMiddleButton( puiNewEvent );
72 }
73
74
QueryRTMiddleButton(UIEventKind * const puiNewEvent)75 static void QueryRTMiddleButton(UIEventKind* const puiNewEvent)
76 {
77 //static BOOLEAN fClickHoldIntercepted = FALSE;
78 //static BOOLEAN fClickIntercepted = FALSE;
79 static UINT32 uiSingleClickTime;
80 static BOOLEAN fDoubleClickIntercepted = FALSE;
81 static BOOLEAN fValidDoubleClickPossible = FALSE;
82
83 if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
84 {
85 const GridNo usMapPos = GetMouseMapPos();
86 if (usMapPos == NOWHERE) return;
87
88 // MIDDLE MOUSE BUTTON
89 if ( gViewportRegion.ButtonState & MSYS_MIDDLE_BUTTON )
90 {
91 if ( !fMiddleButtonDown )
92 {
93 fMiddleButtonDown = TRUE;
94 RESETCOUNTER( MMOUSECLICK_DELAY_COUNTER );
95 }
96 }
97 else
98 {
99 if ( fMiddleButtonDown )
100 {
101 // OK , FOR DOUBLE CLICKS - TAKE TIME STAMP & RECORD EVENT
102 if ( ( GetJA2Clock() - uiSingleClickTime ) < 300 )
103 {
104 // CHECK HERE FOR DOUBLE CLICK EVENTS
105 if ( fValidDoubleClickPossible )
106 {
107 fDoubleClickIntercepted = TRUE;
108
109 // Do stuff....
110 }
111 }
112
113 // Capture time!
114 uiSingleClickTime = GetJA2Clock();
115
116 fValidDoubleClickPossible = TRUE;
117
118 if ( !fDoubleClickIntercepted )
119 {
120 // CHECK COMBINATIONS ETC...
121
122 if (gamepolicy(middle_mouse_look)) *puiNewEvent = LC_LOOK;
123 }
124
125 // Reset flag
126 fMiddleButtonDown = FALSE;
127 //fClickHoldIntercepted = FALSE;
128 //fClickIntercepted = FALSE;
129 fDoubleClickIntercepted = FALSE;
130
131
132 // Reset counter
133 RESETCOUNTER( MMOUSECLICK_DELAY_COUNTER );
134 }
135 }
136 }
137 }
138
QueryRTLeftButton(UIEventKind * const puiNewEvent)139 static void QueryRTLeftButton(UIEventKind* const puiNewEvent)
140 {
141 static UINT32 uiSingleClickTime;
142 static BOOLEAN fDoubleClickIntercepted = FALSE;
143 static BOOLEAN fValidDoubleClickPossible = FALSE;
144 static BOOLEAN fCanCheckForSpeechAdvance = FALSE;
145
146 SOLDIERTYPE* const sel = GetSelectedMan();
147
148 // LEFT MOUSE BUTTON
149 if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
150 {
151 if (sel != NULL && sel->pTempObject != NULL) return;
152
153 const GridNo usMapPos = GetMouseMapPos();
154 if (usMapPos == NOWHERE && !gfUIShowExitSouth) return;
155
156 if ( gViewportRegion.ButtonState & MSYS_LEFT_BUTTON )
157 {
158 if ( !fLeftButtonDown )
159 {
160 fLeftButtonDown = TRUE;
161 gfRTHaveClickedRightWhileLeftDown = FALSE;
162 RESETCOUNTER( LMOUSECLICK_DELAY_COUNTER );
163
164 if (g_ui_message_overlay == NULL)
165 {
166 if ( gpItemPointer == NULL )
167 {
168 switch( gCurrentUIMode )
169 {
170 case ACTION_MODE:
171 if (sel != NULL && gpItemPointer == NULL)
172 {
173 // OK, check for needing ammo
174 if (HandleUIReloading(sel))
175 {
176 gfRTClickLeftHoldIntercepted = TRUE;
177 //fLeftButtonDown = FALSE;
178 }
179 else
180 {
181 if (sel->bDoBurst)
182 {
183 sel->sStartGridNo = usMapPos;
184 ResetBurstLocations();
185 *puiNewEvent = A_CHANGE_TO_CONFIM_ACTION;
186 }
187 else
188 {
189 gfRTClickLeftHoldIntercepted = TRUE;
190
191 if (UIMouseOnValidAttackLocation(sel))
192 {
193 // OK< going into confirm will call a function that will automatically move
194 // us to shoot in most vases ( grenades need a confirm mode regardless )
195 *puiNewEvent = A_CHANGE_TO_CONFIM_ACTION;
196 //*puiNewEvent = CA_MERC_SHOOT;
197 }
198 }
199 }
200 }
201 break;
202
203
204 case MOVE_MODE:
205
206 gfUICanBeginAllMoveCycle = TRUE;
207
208 if ( !HandleCheckForExitArrowsInput( FALSE ) &&
209 gpItemPointer == NULL )
210 {
211 if (gUIFullTarget != NULL && guiUIFullTargetFlags & OWNED_MERC)
212 {
213 // Reset , if this guy is selected merc, reset any multi selections...
214 if (gUIFullTarget == sel)
215 {
216 ResetMultiSelection( );
217 }
218 }
219 else
220 {
221 INT8 const bReturnCode = HandleMoveModeInteractiveClick(usMapPos);
222 if ( bReturnCode == -1 )
223 {
224 //gfRTClickLeftHoldIntercepted = TRUE;
225 }
226 else if ( bReturnCode == -2 )
227 {
228 //if ( gGameSettings.fOptions[ TOPTION_RTCONFIRM ] )
229 //{
230 // *puiNewEvent = C_WAIT_FOR_CONFIRM;
231 // gfPlotNewMovement = TRUE;
232 //}/
233 //else
234 }
235 else if ( bReturnCode == -3 )
236 {
237 gfRTClickLeftHoldIntercepted = TRUE;
238 }
239 else if ( bReturnCode == 0 )
240 {
241 if (sel != NULL)
242 {
243 if (UIOKMoveDestination(sel, usMapPos) == 1)
244 {
245 if ( gsCurrentActionPoints != 0 )
246 {
247 // We're on terrain in which we can walk, walk
248 // If we're on terrain,
249 if ( !gGameSettings.fOptions[ TOPTION_RTCONFIRM ] )
250 {
251 *puiNewEvent = C_WAIT_FOR_CONFIRM;
252 gfPlotNewMovement = TRUE;
253 }
254 }
255 }
256 }
257 }
258 }
259 //gfRTClickLeftHoldIntercepted = TRUE;
260 }
261 else
262 {
263 gfRTClickLeftHoldIntercepted = TRUE;
264 fIgnoreLeftUp = TRUE;
265 }
266
267 break;
268 default:
269 break;
270 }
271 }
272 }
273 if ( gfUIWaitingForUserSpeechAdvance )
274 {
275 fCanCheckForSpeechAdvance = TRUE;
276 }
277
278 }
279
280 if ( gpItemPointer == NULL )
281 {
282 if (g_ui_message_overlay == NULL && !gfRTHaveClickedRightWhileLeftDown)
283 {
284 // HERE FOR CLICK-DRAG CLICK
285 switch( gCurrentUIMode )
286 {
287 case MOVE_MODE:
288 case CONFIRM_MOVE_MODE:
289 {
290 // First check if we clicked on a guy, if so, make selected if it's ours
291 const SOLDIERTYPE* const s = FindSoldierFromMouse();
292 if (s != NULL)
293 {
294 // Select guy
295 if (s == sel && s->bLife >= OKLIFE && !(s->uiStatusFlags & SOLDIER_VEHICLE))
296 {
297 *puiNewEvent = M_CHANGE_TO_ADJPOS_MODE;
298 }
299 }
300 else
301 {
302 // OK, change to rubber banding mode..
303 // Have we started this yet?
304 if ( !gfStartLookingForRubberBanding && !gRubberBandActive )
305 {
306 gfStartLookingForRubberBanding = TRUE;
307 gusRubberBandX = gusMouseXPos;
308 gusRubberBandY = gusMouseYPos;
309 }
310 else
311 {
312 // Have we moved....?
313 if ( ABS( gusMouseXPos - gusRubberBandX ) > 10 || ABS( gusMouseYPos - gusRubberBandY ) > 10 )
314 {
315 gfStartLookingForRubberBanding = FALSE;
316
317 // Stop scrolling:
318 gfIgnoreScrolling = TRUE;
319
320 // Anchor cursor....
321 RestrictMouseToXYXY( 0, 0, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y );
322
323 // OK, settup anchor....
324 gRubberBandRect.iLeft = gusRubberBandX;
325 gRubberBandRect.iTop = gusRubberBandY;
326
327 gRubberBandActive = TRUE;
328
329 // ATE: If we have stopped scrolling.....
330 if (g_scroll_inertia)
331 {
332 SetRenderFlags( RENDER_FLAG_FULL | RENDER_FLAG_CHECKZ );
333
334 // Restore Interface!
335 RestoreInterface( );
336
337 DeleteVideoOverlaysArea( );
338
339 g_scroll_inertia = false;
340 }
341
342 *puiNewEvent = RB_ON_TERRAIN;
343 return;
344 }
345 }
346 }
347 break;
348 }
349 default:
350 break;
351 }
352 }
353 }
354 }
355 else
356 {
357 if ( fLeftButtonDown )
358 {
359 if ( !fIgnoreLeftUp )
360 {
361 // set flag for handling single clicks
362 // OK , FOR DOUBLE CLICKS - TAKE TIME STAMP & RECORD EVENT
363 if ( ( GetJA2Clock() - uiSingleClickTime ) < 300 )
364 {
365 // CHECK HERE FOR DOUBLE CLICK EVENTS
366 if ( fValidDoubleClickPossible )
367 {
368 if ( gpItemPointer == NULL )
369 {
370 fDoubleClickIntercepted = TRUE;
371
372 // First check if we clicked on a guy, if so, make selected if it's ours
373 if (sel != NULL)
374 {
375 // Set movement mode
376 // OK, only change this if we are stationary!
377 //if (gAnimControl[s->usAnimState].uiFlags & ANIM_STATIONARY)
378 //if (sel->usAnimState == WALKING)
379 {
380 sel->fUIMovementFast = TRUE;
381 *puiNewEvent = C_MOVE_MERC;
382 }
383 }
384 }
385 }
386
387 }
388
389 // Capture time!
390 uiSingleClickTime = GetJA2Clock();
391
392 fValidDoubleClickPossible = FALSE;
393
394 if ( !fDoubleClickIntercepted )
395 {
396 // FIRST CHECK FOR ANYTIME ( NON-INTERVAL ) CLICKS
397 switch( gCurrentUIMode )
398 {
399 case ADJUST_STANCE_MODE:
400
401 // If button has come up, change to mocve mode
402 *puiNewEvent = PADJ_ADJUST_STANCE;
403 break;
404 default:
405 break;
406 }
407
408 // CHECK IF WE CLICKED-HELD
409 if ( COUNTERDONE( LMOUSECLICK_DELAY_COUNTER ) && gpItemPointer != NULL )
410 {
411 // LEFT CLICK-HOLD EVENT
412 // Switch on UI mode
413 switch( gCurrentUIMode )
414 {
415 case CONFIRM_ACTION_MODE:
416 case ACTION_MODE:
417 if (sel != NULL && sel->bDoBurst)
418 {
419 sel->sEndGridNo = usMapPos;
420
421 gfBeginBurstSpreadTracking = FALSE;
422
423 if (sel->sEndGridNo != sel->sStartGridNo )
424 {
425 sel->fDoSpread = TRUE;
426 PickBurstLocations(sel);
427 *puiNewEvent = CA_MERC_SHOOT;
428 }
429 else
430 {
431 sel->fDoSpread = FALSE;
432 }
433 gfRTClickLeftHoldIntercepted = TRUE;
434 }
435 break;
436 default:
437 break;
438 }
439 }
440 //else
441 {
442 //LEFT CLICK NORMAL EVENT
443 // Switch on UI mode
444 if ( !gfRTClickLeftHoldIntercepted )
445 {
446 if (g_ui_message_overlay != NULL)
447 {
448 EndUIMessage( );
449 }
450 else
451 {
452 if ( !HandleCheckForExitArrowsInput( TRUE ) )
453 {
454 if ( gpItemPointer != NULL )
455 {
456 if ( HandleItemPointerClick( usMapPos ) )
457 {
458 // getout of mode
459 EndItemPointer( );
460
461 *puiNewEvent = A_CHANGE_TO_MOVE;
462 }
463
464 }
465 else
466 {
467 // Check for wiating for keyboard advance
468 if ( gfUIWaitingForUserSpeechAdvance && fCanCheckForSpeechAdvance )
469 {
470 // We have a key, advance!
471 DialogueAdvanceSpeech( );
472 }
473 else
474 {
475 switch( gCurrentUIMode )
476 {
477
478 case MENU_MODE:
479
480 // If we get a hit here and we're in menu mode, quit the menu mode
481 EndMenuEvent( guiCurrentEvent );
482 break;
483
484 case IDLE_MODE:
485 {
486 // First check if we clicked on a guy, if so, make selected if it's ours
487 const SOLDIERTYPE* const s = FindSoldierFromMouse();
488 if (s && IsOwnedMerc(*s))
489 {
490 *puiNewEvent = I_SELECT_MERC;
491 }
492 break;
493 }
494
495 case HANDCURSOR_MODE:
496
497 HandleHandCursorClick( usMapPos, puiNewEvent );
498 break;
499
500 case ACTION_MODE:
501 *puiNewEvent = CA_MERC_SHOOT;
502 break;
503
504 case CONFIRM_MOVE_MODE:
505 if (sel != NULL)
506 {
507 if (sel->usAnimState == RUNNING)
508 {
509 sel->fUIMovementFast = 2;
510 }
511 *puiNewEvent = C_MOVE_MERC;
512 }
513
514 //*puiNewEvent = C_MOVE_MERC;
515
516 //if ( gGameSettings.fOptions[ TOPTION_RTCONFIRM ] )
517 {
518 fValidDoubleClickPossible = TRUE;
519 }
520 break;
521
522 case CONFIRM_ACTION_MODE:
523 *puiNewEvent = CA_MERC_SHOOT;
524 break;
525
526 case MOVE_MODE:
527
528 if ( !HandleCheckForExitArrowsInput( FALSE ) && gpItemPointer == NULL )
529 {
530 // First check if we clicked on a guy, if so, make selected if it's ours
531 if (gUIFullTarget != NULL && guiUIFullTargetFlags & OWNED_MERC)
532 {
533 if ( !( guiUIFullTargetFlags & UNCONSCIOUS_MERC ) )
534 {
535 // Select guy
536 SOLDIERTYPE* const pSoldier = gUIFullTarget;
537 if (pSoldier != NULL && gpItemPointer == NULL)
538 {
539 if( pSoldier->bAssignment >= ON_DUTY && !(pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) )
540 {
541 PopupAssignmentMenuInTactical();
542 }
543 else
544 {
545 if ( !_KeyDown( ALT ) )
546 {
547 ResetMultiSelection( );
548 *puiNewEvent = I_SELECT_MERC;
549 }
550 else
551 {
552 if ( pSoldier->uiStatusFlags & SOLDIER_MULTI_SELECTED )
553 {
554 pSoldier->uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
555 }
556 else
557 {
558 pSoldier->uiStatusFlags |= (SOLDIER_MULTI_SELECTED );
559 // Say Confimation...
560 if( !gGameSettings.fOptions[ TOPTION_MUTE_CONFIRMATIONS ] )
561 DoMercBattleSound( pSoldier, BATTLE_SOUND_ATTN1 );
562
563 // OK, if we have a selected guy.. make him part too....
564 if (sel != NULL)
565 {
566 sel->uiStatusFlags |= SOLDIER_MULTI_SELECTED;
567 }
568 }
569
570 gfIgnoreOnSelectedGuy = TRUE;
571
572
573 EndMultiSoldierSelection( FALSE );
574 }
575 }
576 }
577 else
578 {
579 if ( !_KeyDown( ALT ) )
580 {
581 ResetMultiSelection( );
582 *puiNewEvent = I_SELECT_MERC;
583 }
584 else
585 {
586 if ( pSoldier->uiStatusFlags & SOLDIER_MULTI_SELECTED )
587 {
588 pSoldier->uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
589 }
590 else
591 {
592 pSoldier->uiStatusFlags |= (SOLDIER_MULTI_SELECTED );
593 // Say Confimation...
594 if( !gGameSettings.fOptions[ TOPTION_MUTE_CONFIRMATIONS ] )
595 DoMercBattleSound( pSoldier, BATTLE_SOUND_ATTN1 );
596 }
597
598 // OK, if we have a selected guy.. make him part too....
599 if (sel != NULL)
600 {
601 sel->uiStatusFlags |= SOLDIER_MULTI_SELECTED;
602 }
603
604 gfIgnoreOnSelectedGuy = TRUE;
605
606 EndMultiSoldierSelection( FALSE );
607 }
608 }
609 }
610 gfRTClickLeftHoldIntercepted = TRUE;
611 }
612 else
613 {
614 INT8 const bReturnCode = HandleMoveModeInteractiveClick(usMapPos);
615 if ( bReturnCode == -1 )
616 {
617 gfRTClickLeftHoldIntercepted = TRUE;
618 }
619 else if ( bReturnCode == -2 )
620 {
621 //if ( gGameSettings.fOptions[ TOPTION_RTCONFIRM ] )
622 //{
623 // *puiNewEvent = C_WAIT_FOR_CONFIRM;
624 // gfPlotNewMovement = TRUE;
625 //}/
626 //else
627 //{
628 if (sel != NULL)
629 {
630 BeginDisplayTimedCursor( GetInteractiveTileCursor( guiCurrentUICursor, TRUE ), 300 );
631
632 if (sel->usAnimState != RUNNING)
633 {
634 *puiNewEvent = C_MOVE_MERC;
635 }
636 else if (GetCurInteractiveTile() != NULL)
637 {
638 sel->fUIMovementFast = TRUE;
639 *puiNewEvent = C_MOVE_MERC;
640 }
641 fValidDoubleClickPossible = TRUE;
642 }
643 //}
644 }
645 else if ( bReturnCode == 0 )
646 {
647 if (sel != NULL)
648 {
649 // First check if we clicked on a guy, if so, make selected if it's ours
650 const SOLDIERTYPE* const s = FindSoldierFromMouse();
651 if (s && IsOwnedMerc(*s))
652 {
653 // Select guy
654 *puiNewEvent = I_SELECT_MERC;
655 gfRTClickLeftHoldIntercepted = TRUE;
656 }
657 else
658 {
659 if ( gsCurrentActionPoints == 0 && !gfUIAllMoveOn && !gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
660 {
661 ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
662 gfRTClickLeftHoldIntercepted = TRUE;
663 }
664 else
665 {
666 const BOOLEAN fResult = UIOKMoveDestination(sel, usMapPos);
667 if (fResult == 1)
668 {
669 if (gfUIAllMoveOn)
670 {
671 // ATE: Select everybody in squad and make move!
672 // Make move!
673 *puiNewEvent = C_MOVE_MERC;
674 fValidDoubleClickPossible = TRUE;
675 }
676 else
677 {
678 // We're on terrain in which we can walk, walk
679 // If we're on terrain,
680 if (gGameSettings.fOptions[TOPTION_RTCONFIRM])
681 {
682 *puiNewEvent = C_WAIT_FOR_CONFIRM;
683 gfPlotNewMovement = TRUE;
684 }
685 else
686 {
687 *puiNewEvent = C_MOVE_MERC;
688 fValidDoubleClickPossible = TRUE;
689 }
690 }
691 }
692 else
693 {
694 if (fResult == 2)
695 {
696 ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[NOBODY_USING_REMOTE_STR]);
697 }
698 gfRTClickLeftHoldIntercepted = TRUE;
699 }
700 }
701 }
702 }
703 }
704 }
705 //gfRTClickLeftHoldIntercepted = TRUE;
706 }
707 else
708 {
709 gfRTClickLeftHoldIntercepted = TRUE;
710 }
711 break;
712
713 case LOOKCURSOR_MODE:
714 // If we cannot actually do anything, return to movement mode
715 *puiNewEvent = LC_LOOK;
716 break;
717
718 case JUMPOVER_MODE:
719
720 *puiNewEvent = JP_JUMP;
721 break;
722
723 case TALKCURSOR_MODE:
724 if ( HandleTalkInit( ) )
725 {
726 *puiNewEvent = TA_TALKINGMENU;
727 }
728 break;
729
730 case GETTINGITEM_MODE:
731
732 // Remove menu!
733 // RemoveItemPickupMenu( );
734 break;
735
736 case TALKINGMENU_MODE:
737
738 //HandleTalkingMenuEscape( TRUE );
739 break;
740
741 case EXITSECTORMENU_MODE:
742
743 RemoveSectorExitMenu( FALSE );
744 break;
745
746 case OPENDOOR_MENU_MODE:
747
748 CancelOpenDoorMenu( );
749 HandleOpenDoorMenu( );
750 *puiNewEvent = A_CHANGE_TO_MOVE;
751 break;
752
753 case RUBBERBAND_MODE:
754
755 EndRubberBanding( );
756 *puiNewEvent = A_CHANGE_TO_MOVE;
757 break;
758
759 default:
760 break;
761 }
762 }
763
764 }
765 }
766 }
767 }
768 }
769 }
770 }
771
772 // Reset flag
773 fLeftButtonDown = FALSE;
774 fIgnoreLeftUp = FALSE;
775 gfRTClickLeftHoldIntercepted = FALSE;
776 fDoubleClickIntercepted = FALSE;
777 fCanCheckForSpeechAdvance = FALSE;
778 gfStartLookingForRubberBanding = FALSE;
779
780 // Reset counter
781 RESETCOUNTER( LMOUSECLICK_DELAY_COUNTER );
782
783 }
784
785 }
786
787 }
788 else
789 {
790 // Set mouse down to false
791 //fLeftButtonDown = FALSE;
792
793 //fCanCheckForSpeechAdvance = FALSE;
794
795 // OK, handle special cases like if we are dragging and holding for a burst spread and
796 // release mouse over another mouse region
797 if ( gfBeginBurstSpreadTracking )
798 {
799 if (sel != NULL) sel->fDoSpread = FALSE;
800 gfBeginBurstSpreadTracking = FALSE;
801 }
802 }
803 }
804
805
QueryRTRightButton(UIEventKind * const puiNewEvent)806 static void QueryRTRightButton(UIEventKind* const puiNewEvent)
807 {
808 static BOOLEAN fClickHoldIntercepted = FALSE;
809 static BOOLEAN fClickIntercepted = FALSE;
810 static UINT32 uiSingleClickTime;
811 static BOOLEAN fDoubleClickIntercepted = FALSE;
812 static BOOLEAN fValidDoubleClickPossible = FALSE;
813
814 if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
815 {
816 const GridNo usMapPos = GetMouseMapPos();
817 if (usMapPos == NOWHERE) return;
818
819 // RIGHT MOUSE BUTTON
820 if ( gViewportRegion.ButtonState & MSYS_RIGHT_BUTTON )
821 {
822 if ( !fRightButtonDown )
823 {
824 fRightButtonDown = TRUE;
825 RESETCOUNTER( RMOUSECLICK_DELAY_COUNTER );
826 }
827
828 // CHECK COMBINATIONS
829 if ( fLeftButtonDown )
830 {
831 //fIgnoreLeftUp = TRUE;
832 gfRTHaveClickedRightWhileLeftDown = TRUE;
833
834 if ( gpItemPointer == NULL )
835 {
836 // ATE:
837 SOLDIERTYPE* const sel = GetSelectedMan();
838 if (sel != NULL)
839 {
840 switch( gCurrentUIMode )
841 {
842 case CONFIRM_MOVE_MODE:
843 case MOVE_MODE:
844
845 if ( !gfUIAllMoveOn )
846 {
847 fValidDoubleClickPossible = TRUE;
848
849 // OK, our first right-click is an all-cycle
850 if ( gfUICanBeginAllMoveCycle )
851 {
852 // ATE: Here, check if we can do this....
853 if (!UIOKMoveDestination(sel, usMapPos))
854 {
855 ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANT_MOVE_THERE_STR ] );
856 gfRTClickLeftHoldIntercepted = TRUE;
857 }
858 //else if ( gsCurrentActionPoints == 0 )
859 //{
860 // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
861 // gfRTClickLeftHoldIntercepted = TRUE;
862 //}
863 else
864 {
865 *puiNewEvent = M_CYCLE_MOVE_ALL;
866 }
867 }
868 fClickHoldIntercepted = TRUE;
869 }
870 default:
871 break;
872 }
873
874 // ATE: Added cancel of burst mode....
875 if ( gfBeginBurstSpreadTracking )
876 {
877 gfBeginBurstSpreadTracking = FALSE;
878 gfRTClickLeftHoldIntercepted = TRUE;
879 sel->fDoSpread = FALSE;
880 fClickHoldIntercepted = TRUE;
881 *puiNewEvent = A_END_ACTION;
882 gCurrentUIMode = MOVE_MODE;
883 }
884
885 }
886 }
887 }
888 else
889 {
890 // IF HERE, DO A CLICK-HOLD IF IN INTERVAL
891 if ( COUNTERDONE( RMOUSECLICK_DELAY_COUNTER ) && !fClickHoldIntercepted )
892 {
893 if ( gpItemPointer == NULL )
894 {
895 // Switch on UI mode
896 switch( gCurrentUIMode )
897 {
898 case IDLE_MODE:
899 case ACTION_MODE:
900 case HANDCURSOR_MODE:
901 case LOOKCURSOR_MODE:
902 case TALKCURSOR_MODE:
903 case MOVE_MODE:
904 {
905 const SOLDIERTYPE* const tgt = gUIFullTarget;
906 if (tgt != NULL &&
907 !(tgt->uiStatusFlags & SOLDIER_VEHICLE) &&
908 guiUIFullTargetFlags & OWNED_MERC &&
909 guiUIFullTargetFlags & VISIBLE_MERC &&
910 !(guiUIFullTargetFlags & DEAD_MERC))
911 {
912 PopupAssignmentMenuInTactical();
913 fClickHoldIntercepted = TRUE;
914 }
915 else if (GetSelectedMan() != NULL)
916 {
917 fShowAssignmentMenu = FALSE;
918 CreateDestroyAssignmentPopUpBoxes();
919 DetermineWhichAssignmentMenusCanBeShown();
920
921 // ATE:
922 if ( !fClickHoldIntercepted )
923 {
924 *puiNewEvent = U_MOVEMENT_MENU;
925 fClickHoldIntercepted = TRUE;
926 }
927 }
928 break;
929 }
930 default:
931 break;
932 }
933 }
934 }
935
936 }
937
938 }
939 else
940 {
941 if ( fRightButtonDown )
942 {
943 // OK , FOR DOUBLE CLICKS - TAKE TIME STAMP & RECORD EVENT
944 if ( ( GetJA2Clock() - uiSingleClickTime ) < 300 )
945 {
946 // CHECK HERE FOR DOUBLE CLICK EVENTS
947 if ( fValidDoubleClickPossible )
948 {
949 fDoubleClickIntercepted = TRUE;
950
951 // Do stuff....
952 // OK, check if left button down...
953 if ( fLeftButtonDown )
954 {
955 if ( gpItemPointer == NULL )
956 {
957 if ( !fClickIntercepted && !fClickHoldIntercepted )
958 {
959 // ATE:
960 if (GetSelectedMan() != NULL)
961 {
962 //fIgnoreLeftUp = TRUE;
963 switch( gCurrentUIMode )
964 {
965 case CONFIRM_MOVE_MODE:
966 case MOVE_MODE:
967 if ( gfUIAllMoveOn )
968 {
969 // OK, now we wish to run!
970 gfUIAllMoveOn = 2;
971 }
972 default:
973 break;
974 }
975 }
976
977 }
978 }
979 }
980 }
981 }
982
983 // Capture time!
984 uiSingleClickTime = GetJA2Clock();
985
986 fValidDoubleClickPossible = TRUE;
987
988 if ( !fDoubleClickIntercepted )
989 {
990 // CHECK COMBINATIONS
991 if ( fLeftButtonDown )
992 {
993 if ( gpItemPointer == NULL )
994 {
995 if ( !fClickHoldIntercepted && !fClickIntercepted )
996 {
997 // ATE:
998 if (GetSelectedMan() != NULL)
999 {
1000 //fIgnoreLeftUp = TRUE;
1001 switch( gCurrentUIMode )
1002 {
1003 case CONFIRM_MOVE_MODE:
1004 case MOVE_MODE:
1005
1006 if ( gfUIAllMoveOn )
1007 {
1008 gfUIAllMoveOn = FALSE;
1009 gfUICanBeginAllMoveCycle = TRUE;
1010 }
1011 default:
1012 break;
1013
1014 }
1015 }
1016 }
1017 }
1018 }
1019 else
1020 {
1021 if ( !fClickHoldIntercepted && !fClickIntercepted )
1022 {
1023 if ( gpItemPointer == NULL )
1024 {
1025 // ATE:
1026 SOLDIERTYPE* const sel = GetSelectedMan();
1027 if (sel != NULL)
1028 {
1029 // Switch on UI mode
1030 switch( gCurrentUIMode )
1031 {
1032 case IDLE_MODE:
1033
1034 break;
1035
1036 case CONFIRM_MOVE_MODE:
1037 case MOVE_MODE:
1038 case TALKCURSOR_MODE:
1039 // We have here a change to action mode
1040 *puiNewEvent = M_CHANGE_TO_ACTION;
1041 fClickIntercepted = TRUE;
1042 break;
1043
1044 case ACTION_MODE:
1045 // We have here a change to move mode
1046 *puiNewEvent = A_END_ACTION;
1047 fClickIntercepted = TRUE;
1048 break;
1049
1050 case CONFIRM_ACTION_MODE:
1051 HandleRightClickAdjustCursor(sel, usMapPos);
1052 fClickIntercepted = TRUE;
1053 break;
1054
1055 case MENU_MODE:
1056 // If we get a hit here and we're in menu mode, quit the menu mode
1057 EndMenuEvent( guiCurrentEvent );
1058 fClickIntercepted = TRUE;
1059 break;
1060
1061 case HANDCURSOR_MODE:
1062 // If we cannot actually do anything, return to movement mode
1063 *puiNewEvent = A_CHANGE_TO_MOVE;
1064 break;
1065
1066 case LOOKCURSOR_MODE:
1067
1068 // If we cannot actually do anything, return to movement mode
1069 *puiNewEvent = A_CHANGE_TO_MOVE;
1070 break;
1071
1072 default:
1073 break;
1074 }
1075 }
1076 }
1077 else
1078 {
1079 if (gUIFullTarget != NULL)
1080 {
1081 gfItemPointerDifferentThanDefault = !gfItemPointerDifferentThanDefault;
1082 }
1083 }
1084 }
1085 }
1086 }
1087
1088 // Reset flag
1089 fRightButtonDown = FALSE;
1090 fClickHoldIntercepted = FALSE;
1091 fClickIntercepted = FALSE;
1092 fDoubleClickIntercepted = FALSE;
1093
1094
1095 // Reset counter
1096 RESETCOUNTER( RMOUSECLICK_DELAY_COUNTER );
1097 }
1098 }
1099 }
1100 }
1101
1102
GetRTMousePositionInput(UIEventKind * const puiNewEvent)1103 void GetRTMousePositionInput(UIEventKind* const puiNewEvent)
1104 {
1105 static const SOLDIERTYPE* MoveTargetSoldier = NULL;
1106
1107 static UINT16 usOldMapPos = 0;
1108
1109 const GridNo usMapPos = GetMouseMapPos();
1110 if (usMapPos == NOWHERE) return;
1111
1112 if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
1113 {
1114 // Check if we have an item in our hands...
1115 if ( gpItemPointer != NULL )
1116 {
1117 *puiNewEvent = A_ON_TERRAIN;
1118 return;
1119 }
1120
1121 // Switch on modes
1122 switch( gCurrentUIMode )
1123 {
1124 case RUBBERBAND_MODE:
1125 // ATE: Make sure!
1126 if (!gRubberBandActive)
1127 {
1128 *puiNewEvent = M_ON_TERRAIN;
1129 }
1130 else
1131 {
1132 *puiNewEvent = RB_ON_TERRAIN;
1133 }
1134 break;
1135
1136 case JUMPOVER_MODE:
1137
1138 // ATE: Make sure!
1139 if ( gsJumpOverGridNo != usMapPos )
1140 {
1141 *puiNewEvent = A_CHANGE_TO_MOVE;
1142 }
1143 else
1144 {
1145 *puiNewEvent = JP_ON_TERRAIN;
1146 }
1147 break;
1148
1149 case LOCKUI_MODE:
1150 *puiNewEvent = LU_ON_TERRAIN;
1151 break;
1152
1153 case IDLE_MODE:
1154 *puiNewEvent = I_ON_TERRAIN;
1155 break;
1156
1157 case ENEMYS_TURN_MODE:
1158 *puiNewEvent = ET_ON_TERRAIN;
1159 break;
1160
1161 case LOOKCURSOR_MODE:
1162 *puiNewEvent = LC_ON_TERRAIN;
1163 break;
1164
1165 case TALKCURSOR_MODE:
1166 if (MoveTargetSoldier != NULL && gUIFullTarget != MoveTargetSoldier)
1167 {
1168 *puiNewEvent = A_CHANGE_TO_MOVE;
1169 return;
1170 }
1171 *puiNewEvent = T_ON_TERRAIN;
1172 break;
1173
1174 case GETTINGITEM_MODE:
1175
1176 break;
1177
1178 case TALKINGMENU_MODE:
1179
1180 if ( HandleTalkingMenu( ) )
1181 {
1182 *puiNewEvent = A_CHANGE_TO_MOVE;
1183 }
1184 break;
1185
1186 case EXITSECTORMENU_MODE:
1187
1188 if ( HandleSectorExitMenu( ) )
1189 {
1190 *puiNewEvent = A_CHANGE_TO_MOVE;
1191 }
1192 break;
1193
1194 case OPENDOOR_MENU_MODE:
1195
1196 if ( HandleOpenDoorMenu( ) )
1197 {
1198 *puiNewEvent = A_CHANGE_TO_MOVE;
1199 }
1200 break;
1201
1202 case HANDCURSOR_MODE:
1203
1204 *puiNewEvent = HC_ON_TERRAIN;
1205 break;
1206
1207 case MOVE_MODE:
1208 {
1209 if ( usMapPos != usOldMapPos )
1210 {
1211 // Set off ALL move....
1212 gfUIAllMoveOn = FALSE;
1213 }
1214
1215 MoveTargetSoldier = NULL;
1216
1217 // Check for being on terrain
1218 const SOLDIERTYPE* const sel = GetSelectedMan();
1219 if (sel != NULL)
1220 {
1221 // get cursor for item
1222 ItemCursor const ubItemCursor = GetActionModeCursor(sel);
1223
1224 if (IsValidJumpLocation(sel, usMapPos, TRUE))
1225 {
1226 *puiNewEvent = JP_ON_TERRAIN;
1227 gsJumpOverGridNo = usMapPos;
1228 return;
1229 }
1230 else
1231 {
1232 const SOLDIERTYPE* const tgt = gUIFullTarget;
1233 if (tgt != NULL)
1234 {
1235 if (IsValidTalkableNPC(tgt, FALSE, FALSE, FALSE) && !_KeyDown(SHIFT) &&
1236 !AM_AN_EPC(sel) && tgt->bTeam != ENEMY_TEAM && !ValidQuickExchangePosition())
1237 {
1238 MoveTargetSoldier = gUIFullTarget;
1239 *puiNewEvent = T_CHANGE_TO_TALKING;
1240 return;
1241 }
1242 else if (ubItemCursor != AIDCURS)
1243 {
1244 // IF it's an ememy, goto confirm action mode
1245 if ( ( guiUIFullTargetFlags & ENEMY_MERC ) &&
1246 ( guiUIFullTargetFlags & VISIBLE_MERC ) &&
1247 !( guiUIFullTargetFlags & DEAD_MERC ) )
1248 {
1249 MoveTargetSoldier = gUIFullTarget;
1250 *puiNewEvent = A_ON_TERRAIN;
1251 return;
1252 }
1253 }
1254 }
1255 }
1256 }
1257 *puiNewEvent = M_ON_TERRAIN;
1258 break;
1259 }
1260
1261 case ACTION_MODE:
1262 {
1263 // First check if we are on a guy, if so, make selected if it's ours
1264 // Check if the guy is visible
1265 gUITargetSoldier = NULL;
1266
1267 const SOLDIERTYPE* const tgt = gUIFullTarget;
1268 if (tgt != NULL)
1269 {
1270 if (IsValidTargetMerc(tgt))
1271 {
1272 gUITargetSoldier = tgt;
1273 if (tgt->bTeam == OUR_TEAM && gUIActionModeChangeDueToMouseOver)
1274 {
1275 *puiNewEvent = A_CHANGE_TO_MOVE;
1276 return;
1277 }
1278 }
1279 }
1280 else
1281 {
1282 if ( gUIActionModeChangeDueToMouseOver )
1283 {
1284 *puiNewEvent = A_CHANGE_TO_MOVE;
1285 return;
1286 }
1287 }
1288 *puiNewEvent = A_ON_TERRAIN;
1289 break;
1290 }
1291
1292 case CONFIRM_MOVE_MODE:
1293
1294 if ( usMapPos != usOldMapPos )
1295 {
1296 // Switch event out of confirm mode
1297 // Set off ALL move....
1298 gfUIAllMoveOn = FALSE;
1299
1300 *puiNewEvent = A_CHANGE_TO_MOVE;
1301 }
1302 break;
1303
1304 case CONFIRM_ACTION_MODE:
1305 {
1306 // DONOT CANCEL IF BURST
1307 SOLDIERTYPE* const sel = GetSelectedMan();
1308 if (sel != NULL && sel->bDoBurst)
1309 {
1310 sel->sEndGridNo = usMapPos;
1311
1312 if (sel->sEndGridNo != sel->sStartGridNo && fLeftButtonDown)
1313 {
1314 sel->fDoSpread = TRUE;
1315 gfBeginBurstSpreadTracking = TRUE;
1316 }
1317
1318 if (sel->fDoSpread)
1319 {
1320 // Accumulate gridno
1321 AccumulateBurstLocation(usMapPos);
1322 *puiNewEvent = CA_ON_TERRAIN;
1323 break;
1324 }
1325 }
1326
1327 // First check if we are on a guy, if so, make selected if it's ours
1328 if (gUIFullTarget != NULL)
1329 {
1330 if (gUITargetSoldier != gUIFullTarget)
1331 {
1332 // Switch event out of confirm mode
1333 *puiNewEvent = CA_END_CONFIRM_ACTION;
1334 }
1335 else
1336 {
1337 *puiNewEvent = CA_ON_TERRAIN;
1338 }
1339 }
1340 else
1341 {
1342 if ( usMapPos != usOldMapPos )
1343 {
1344 // Switch event out of confirm mode
1345 *puiNewEvent = CA_END_CONFIRM_ACTION;
1346
1347 }
1348 else
1349 {
1350 *puiNewEvent = CA_ON_TERRAIN;
1351 }
1352 }
1353 break;
1354 }
1355 default:
1356 break;
1357 }
1358
1359 usOldMapPos = usMapPos;
1360
1361 }
1362 }
1363