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