/** * @brief Performs an appropriate action when a jump point is clicked. * * @param jp Index of the jump point. * @param autonav Whether to autonav to the target. * @return Whether the click was used. */ int input_clickedJump( int jump, int autonav ) { JumpPoint *jp; jp = &cur_system->jumps[ jump ]; if (!jp_isUsable(jp)) return 0; /* Update map path. */ if (player.p->nav_hyperspace != jump) map_select( jp->target, 0 ); if (autonav) { player_targetHyperspaceSet( jump ); player_autonavStart(); return 1; } if (jump == player.p->nav_hyperspace && input_isDoubleClick( (void*)jp )) { if (space_canHyperspace(player.p)) player_jump(); } else player_targetHyperspaceSet( jump ); input_clicked( (void*)jp ); 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 the autonavigation process for the player. */ static void player_autonav (void) { JumpPoint *jp; int ret; double d, t, tint; double vel; switch (player.autonav) { case AUTONAV_JUMP_APPROACH: /* Target jump. */ jp = &cur_system->jumps[ player.p->nav_hyperspace ]; ret = player_autonavApproach( &jp->pos, &d, 0 ); if (ret) player.autonav = AUTONAV_JUMP_BRAKE; else if (!tc_rampdown && (map_npath<=1)) { vel = MIN( 1.5*player.p->speed, VMOD(player.p->solid->vel) ); t = d / vel * (1.2 - .1 * tc_base); /* tint is the integral of the time in per time units. * * tc_mod * ^ * | * |\ * | \ * | \___ * | * +------> time * 0 3 * * We decompose integral in a rectangle (3*1) and a triangle (3*(tc_mod-1.))/2. * This is the "elapsed time" when linearly decreasing the tc_mod. Which we can * use to calculate the actual "game time" that'll pass when decreasing the * tc_mod to 1 during 3 seconds. This can be used then to compare when we want to * start decrementing. */ tint = 3. + 0.5*(3.*(tc_mod-tc_base)); if (t < tint) { tc_rampdown = 1; tc_down = (tc_mod-tc_base) / 3.; } } break; case AUTONAV_JUMP_BRAKE: /* Target jump. */ jp = &cur_system->jumps[ player.p->nav_hyperspace ]; if (player.p->stats.misc_instant_jump) { ret = pilot_interceptPos( player.p, jp->pos.x, jp->pos.y ); if (!ret && space_canHyperspace(player.p)) ret = 1; player_acc = player.p->solid->thrust / player.p->thrust; } else ret = player_autonavBrake(); /* Try to jump or see if braked. */ if (ret) { if (space_canHyperspace(player.p)) player_jump(); player.autonav = AUTONAV_JUMP_APPROACH; } /* See if should ramp down. */ if (!tc_rampdown && (map_npath<=1)) { tc_rampdown = 1; tc_down = (tc_mod-tc_base) / 3.; } break; case AUTONAV_POS_APPROACH: ret = player_autonavApproach( &player.autonav_pos, &d, 1 ); if (ret) { player_message( _("\apAutonav arrived at position.") ); player_autonavEnd(); } else if (!tc_rampdown) player_autonavRampdown(d); break; case AUTONAV_PNT_APPROACH: ret = player_autonavApproach( &player.autonav_pos, &d, 1 ); if (ret) { player_message( _("\apAutonav arrived at \a%c%s\a\0."), planet_getColourChar( planet_get(player.autonavmsg) ), player.autonavmsg ); player_autonavEnd(); } else if (!tc_rampdown) player_autonavRampdown(d); break; } }