/** * @brief Performs an appropriate action when a pilot is clicked. * * @param pilot Index of the pilot. * @return Whether the click was used. */ int input_clickedPilot( unsigned int pilot ) { Pilot *p; if (pilot == PLAYER_ID) return 0; p = pilot_get(pilot); if (pilot == player.p->target && input_isDoubleClick( (void*)p )) { if (pilot_isDisabled(p) || pilot_isFlag(p, PILOT_BOARDABLE)) player_board(); else player_hail(); } else player_targetSet( pilot ); input_clicked( (void*)p ); return 1; }
/** * @brief Handles a click event. */ static void input_clickevent( SDL_Event* event ) { unsigned int pid; Pilot *p; int mx, my, mxr, myr, pntid, jpid; int rx, ry, rh, rw, res; double x, y, m, r, rp, d, dp, px, py; double ang, angp, mouseang; Planet *pnt; JumpPoint *jp; HookParam hparam[2]; /* Generate hook. */ hparam[0].type = HOOK_PARAM_NUMBER; hparam[0].u.num = event->button.button; hparam[1].type = HOOK_PARAM_SENTINAL; hooks_runParam( "mouse", hparam ); /* Handle zoom. */ if (event->button.button == SDL_BUTTON_WHEELUP) { input_clickZoom( 1.1 ); return; } else if (event->button.button == SDL_BUTTON_WHEELDOWN) { input_clickZoom( 0.9 ); return; } /* Middle mouse enables mouse flying. */ if (event->button.button == SDL_BUTTON_MIDDLE) { player_toggleMouseFly(); return; } /* Mouse targetting is left only. */ if (event->button.button != SDL_BUTTON_LEFT) return; /* Player must not be NULL. */ if (player_isFlag(PLAYER_DESTROYED) || (player.p == NULL)) return; px = player.p->solid->pos.x; py = player.p->solid->pos.y; gl_windowToScreenPos( &mx, &my, event->button.x, event->button.y ); gl_screenToGameCoords( &x, &y, (double)mx, (double)my ); if ((mx <= 15 || my <= 15 ) || (my >= gl_screen.h - 15 || mx >= gl_screen.w - 15)) { /* Border */ x = (mx - (gl_screen.w / 2.)) + px; y = (my - (gl_screen.h / 2.)) + py; mouseang = atan2(py - y, px - x); angp = pilot_getNearestAng( player.p, &pid, mouseang, 1 ); ang = system_getClosestAng( cur_system, &pntid, &jpid, x, y, mouseang ); if ((ABS(angle_diff(mouseang, angp)) > M_PI / 64) || ABS(angle_diff(mouseang, ang)) < ABS(angle_diff(mouseang, angp))) pid = PLAYER_ID; /* Pilot angle is too great, or planet/jump is closer. */ if (ABS(angle_diff(mouseang, ang)) > M_PI / 64 ) jpid = pntid = -1; /* Asset angle difference is too great. */ } else { /* Radar targeting requires raw coordinates. */ mxr = event->button.x; myr = gl_screen.rh - event->button.y; gui_radarGetPos( &rx, &ry ); gui_radarGetDim( &rw, &rh ); if ((mxr > rx && mxr <= rx + rw ) && (myr > ry && myr <= ry + rh )) { /* Radar */ m = 1; gui_radarGetRes( &res ); x = (mxr - (rx + rw / 2.)) * res + px; y = (myr - (ry + rh / 2.)) * res + py; } else /* Visual (on-screen) */ m = res = 1. / cam_getZoom(); dp = pilot_getNearestPos( player.p, &pid, x, y, 1 ); d = system_getClosest( cur_system, &pntid, &jpid, x, y ); rp = MAX( 1.5 * PILOT_SIZE_APROX * pilot_get(pid)->ship->gfx_space->sw / 2 * m, 10. * res); if (pntid >=0) { /* Planet is closer. */ pnt = cur_system->planets[ pntid ]; r = MAX( 1.5 * pnt->radius, 100. ); } else if (jpid >= 0) { jp = &cur_system->jumps[ jpid ]; r = MAX( 1.5 * jp->radius, 100. ); } else { r = 0.; } /* Reject pilot if it's too far or a valid asset is closer. */ if (dp > pow2(rp) || (d < pow2(r) && dp < pow2(rp) && dp > d)) pid = PLAYER_ID; if (d > pow2(r)) /* Planet or jump point is too far. */ jpid = pntid = -1; } if (pid != PLAYER_ID) { /* Apply an action if already selected. */ if (!pilot_isFlag(player.p, PILOT_DEAD) && (pid == player.p->target)) { p = pilot_get(pid); if (pilot_isDisabled(p) || pilot_isFlag(p, PILOT_BOARDABLE)) player_board(); else player_hail(); } else player_targetSet( pid ); } else if (pntid >= 0) { /* Planet is closest. */ if (pntid == player.p->nav_planet) { pnt = cur_system->planets[ pntid ]; if (planet_hasService(pnt, PLANET_SERVICE_LAND) && (!areEnemies( player.p->faction, pnt->faction ) || pnt->bribed )) player_land(); else player_hailPlanet(); } else player_targetPlanetSet( pntid ); } else if (jpid >= 0) { /* Jump point is closest. */ jp = &cur_system->jumps[ jpid ]; if (jpid == player.p->nav_hyperspace) { if (space_canHyperspace(player.p)) { if (!paused) player_autonavAbort(NULL); player_jump(); } else player_autonavStart(); } else player_targetHyperspaceSet( jpid ); } }
/** * @brief Handles input to the map overlay. */ int ovr_input( SDL_Event *event ) { unsigned int pid; Pilot *p; int mx, my; double x, y, r, rp; double d, dp; Planet *pnt; JumpPoint *jp; int pntid, jpid; /* We only want mouse events. */ if (event->type != SDL_MOUSEBUTTONDOWN) return 0; /* Player must not be NULL. */ if (player_isFlag(PLAYER_DESTROYED) || (player.p == NULL)) return 0; /* Selection. */ if (event->button.button == SDL_BUTTON_LEFT) { /* Translate from window to screen. */ mx = event->button.x; my = event->button.y; gl_windowToScreenPos( &mx, &my, mx, my ); /* Translate to space coords. */ x = ((double)mx - SCREEN_W/2.) * ovr_res; y = ((double)my - SCREEN_H/2.) * ovr_res; /* Get nearest pilot and jump point/planet. */ dp = pilot_getNearestPos( player.p, &pid, x, y, 1 ); d = system_getClosest( cur_system, &pntid, &jpid, x, y ); p = pilot_get(pid); rp = MAX( 1.5 * PILOT_SIZE_APROX * p->ship->gfx_space->sw / 2, 20.*ovr_res ); if (pntid >=0) { /* Planet is closer. */ pnt = cur_system->planets[ pntid ]; r = MAX( 1.5 * pnt->radius, 20. * ovr_res ); } else if (jpid >= 0) { jp = &cur_system->jumps[ jpid ]; r = MAX( 1.5 * jp->radius, 20. * ovr_res ); } else r = 0.; /* Pilot is closest, or new jump point/planet is the same as the old. */ if ((dp < pow2(rp) && player.p->target != pid) && (dp < d || ((pntid >=0 && player.p->nav_planet == pntid) || (jpid >=0 && player.p->nav_planet == jpid)))) player_targetSet( pid ); else if ((pntid >= 0) && (d < pow2(r))) /* Planet is closest. */ player_targetPlanetSet( pntid ); else if ((jpid >= 0) && (d < pow2(r))) /* Jump point is closest. */ player_targetHyperspaceSet( jpid ); else return 0; return 1; } /* Autogo. */ else if (event->button.button == SDL_BUTTON_RIGHT) { if ((player.p == NULL) || pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) || pilot_isFlag( player.p, PILOT_HYP_PREP ) || pilot_isFlag( player.p, PILOT_HYP_BEGIN ) || pilot_isFlag( player.p, PILOT_HYPERSPACE )) return 1; /* Translate from window to screen. */ mx = event->button.x; my = event->button.y; gl_windowToScreenPos( &mx, &my, mx, my ); /* Translate to space coords. */ x = ((double)mx - SCREEN_W/2.) * ovr_res; y = ((double)my - SCREEN_H/2.) * ovr_res; /* Go to position. */ player_autonavPos( x, y ); return 1; } return 0; }