/** * @brief The pseudo-ai of the beam weapons. * * @param w Weapon to do the thinking. * @param dt Current delta tick. */ static void think_beam( Weapon* w, const double dt ) { (void)dt; Pilot *p, *t; double diff; Vector2d v; /* Get pilot, if pilot is dead beam is destroyed. */ p = pilot_get(w->parent); if (p==NULL) { w->timer = -1.; /* Hack to make it get destroyed next update. */ return; } /* Check if pilot has enough energy left to keep beam active. */ p->energy -= dt*w->outfit->u.bem.energy; if (p->energy < 0.) { p->energy = 0.; w->timer = -1; return; } /* Use mount position. */ pilot_getMount( p, w->mount, &v ); w->solid->pos.x = p->solid->pos.x + v.x; w->solid->pos.y = p->solid->pos.y + v.y; /* Handle aiming. */ switch (w->outfit->type) { case OUTFIT_TYPE_BEAM: w->solid->dir = p->solid->dir; break; case OUTFIT_TYPE_TURRET_BEAM: /* Get target, if target is dead beam stops moving. */ t = pilot_get(w->target); if (t==NULL) { weapon_setTurn( w, 0. ); return; } if (w->target == w->parent) /* Invalid target, tries to follow shooter. */ diff = angle_diff(w->solid->dir, p->solid->dir); else diff = angle_diff(w->solid->dir, /* Get angle to target pos */ vect_angle(&w->solid->pos, &t->solid->pos)); weapon_setTurn( w, CLAMP( -w->outfit->u.bem.turn, w->outfit->u.bem.turn, 10 * diff * w->outfit->u.bem.turn )); break; default: return; } }
/** * @brief Actually handles the shooting, how often the player.p can shoot and such. * * @param p Pilot that is shooting. * @param w Pilot's outfit to shoot. * @param time Expected flight time. * @return 0 if nothing was shot and 1 if something was shot. */ static int pilot_shootWeapon( Pilot* p, PilotOutfitSlot* w, double time ) { Vector2d vp, vv; double rate_mod, energy_mod; double energy; int j; /* Make sure weapon has outfit. */ if (w->outfit == NULL) return 0; /* Reset beam shut-off if needed. */ if (outfit_isBeam(w->outfit) && w->outfit->u.bem.min_duration) w->stimer = INFINITY; /* check to see if weapon is ready */ if (w->timer > 0.) return 0; /* Calculate rate modifier. */ pilot_getRateMod( &rate_mod, &energy_mod, p, w->outfit ); /* Get weapon mount position. */ pilot_getMount( p, w, &vp ); vp.x += p->solid->pos.x; vp.y += p->solid->pos.y; /* Modify velocity to take into account the rotation. */ vect_cset( &vv, p->solid->vel.x + vp.x*p->solid->dir_vel, p->solid->vel.y + vp.y*p->solid->dir_vel ); /* * regular bolt weapons */ if (outfit_isBolt(w->outfit)) { /* enough energy? */ if (outfit_energy(w->outfit)*energy_mod > p->energy) return 0; energy = outfit_energy(w->outfit)*energy_mod; p->energy -= energy; pilot_heatAddSlot( p, w ); weapon_add( w->outfit, w->heat_T, p->solid->dir, &vp, &p->solid->vel, p, p->target, time ); } /* * Beam weapons. */ else if (outfit_isBeam(w->outfit)) { /* Don't fire if the existing beam hasn't been destroyed yet. */ if (w->u.beamid > 0) return 0; /* Check if enough energy to last a second. */ if (outfit_energy(w->outfit)*energy_mod > p->energy) return 0; /** @todo Handle warmup stage. */ w->state = PILOT_OUTFIT_ON; w->u.beamid = beam_start( w->outfit, p->solid->dir, &vp, &p->solid->vel, p, p->target, w ); w->timer = w->outfit->u.bem.duration; return 1; /* Return early due to custom timer logic. */ } /* * missile launchers * * must be a secondary weapon */ else if (outfit_isLauncher(w->outfit)) { /* Shooter can't be the target - sanity check for the player.p */ if ((w->outfit->u.lau.ammo->u.amm.ai != AMMO_AI_DUMB) && (p->id==p->target)) return 0; /* Must have ammo left. */ if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0)) return 0; /* enough energy? */ if (outfit_energy(w->u.ammo.outfit)*energy_mod > p->energy) return 0; energy = outfit_energy(w->u.ammo.outfit)*energy_mod; p->energy -= energy; pilot_heatAddSlot( p, w ); weapon_add( w->outfit, w->heat_T, p->solid->dir, &vp, &p->solid->vel, p, p->target, time ); w->u.ammo.quantity -= 1; /* we just shot it */ p->mass_outfit -= w->u.ammo.outfit->mass; p->solid->mass -= w->u.ammo.outfit->mass; pilot_updateMass( p ); /* If last ammo was shot, update the range */ if (w->u.ammo.quantity <= 0) { for (j=0; j<PILOT_WEAPON_SETS; j++) pilot_weapSetUpdateRange( &p->weapon_sets[j] ); } } /* * Fighter bays. */ else if (outfit_isFighterBay(w->outfit)) { /* Must have ammo left. */ if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0)) return 0; /* Create the escort. */ escort_create( p, w->u.ammo.outfit->u.fig.ship, &vp, &p->solid->vel, p->solid->dir, ESCORT_TYPE_BAY, 1 ); w->u.ammo.quantity -= 1; /* we just shot it */ p->mass_outfit -= w->u.ammo.outfit->mass; w->u.ammo.deployed += 1; /* Mark as deployed. */ pilot_updateMass( p ); } else WARN(_("Shooting unknown weapon type: %s"), w->outfit->name); /* Reset timer. */ w->timer += rate_mod * outfit_delay( w->outfit ); return 1; }
/** * @brief Actually handles the shooting, how often the player.p can shoot and such. * * @param p Pilot that is shooting. * @param w Pilot's outfit to shoot. * @return 0 if nothing was shot and 1 if something was shot. */ static int pilot_shootWeapon( Pilot* p, PilotOutfitSlot* w ) { Vector2d vp, vv; double rate_mod, energy_mod; double energy; /* Make sure weapon has outfit. */ if (w->outfit == NULL) return 0; /* check to see if weapon is ready */ if (w->timer > 0.) return 0; /* Calculate rate modifier. */ pilot_getRateMod( &rate_mod, &energy_mod, p, w->outfit ); /* Get weapon mount position. */ pilot_getMount( p, w, &vp ); vp.x += p->solid->pos.x; vp.y += p->solid->pos.y; /* Modify velocity to take into account the rotation. */ vect_cset( &vv, p->solid->vel.x + vp.x*p->solid->dir_vel, p->solid->vel.y + vp.y*p->solid->dir_vel ); /* * regular bolt weapons */ if (outfit_isBolt(w->outfit)) { /* enough energy? */ if (outfit_energy(w->outfit)*energy_mod > p->energy) return 0; energy = outfit_energy(w->outfit)*energy_mod; p->energy -= energy; pilot_heatAddSlot( p, w ); weapon_add( w->outfit, w->heat_T, p->solid->dir, &vp, &p->solid->vel, p, p->target ); } /* * Beam weapons. */ else if (outfit_isBeam(w->outfit)) { /* Check if enough energy to last a second. */ if (outfit_energy(w->outfit)*energy_mod > p->energy) return 0; /** @todo Handle warmup stage. */ w->state = PILOT_OUTFIT_ON; w->u.beamid = beam_start( w->outfit, p->solid->dir, &vp, &p->solid->vel, p, p->target, w ); } /* * missile launchers * * must be a secondary weapon */ else if (outfit_isLauncher(w->outfit)) { /* Shooter can't be the target - sanity check for the player.p */ if ((w->outfit->u.lau.ammo->u.amm.ai > 0) && (p->id==p->target)) return 0; /* Must have ammo left. */ if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0)) return 0; /* enough energy? */ if (outfit_energy(w->u.ammo.outfit)*energy_mod > p->energy) return 0; energy = outfit_energy(w->u.ammo.outfit)*energy_mod; p->energy -= energy; pilot_heatAddSlot( p, w ); weapon_add( w->outfit, w->heat_T, p->solid->dir, &vp, &p->solid->vel, p, p->target ); w->u.ammo.quantity -= 1; /* we just shot it */ p->mass_outfit -= w->u.ammo.outfit->mass; pilot_updateMass( p ); } /* * Fighter bays. */ else if (outfit_isFighterBay(w->outfit)) { /* Must have ammo left. */ if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0)) return 0; /* Create the escort. */ escort_create( p, w->u.ammo.outfit->u.fig.ship, &vp, &p->solid->vel, p->solid->dir, ESCORT_TYPE_BAY, 1 ); w->u.ammo.quantity -= 1; /* we just shot it */ p->mass_outfit -= w->u.ammo.outfit->mass; w->u.ammo.deployed += 1; /* Mark as deployed. */ pilot_updateMass( p ); } else WARN("Shooting unknown weapon type: %s", w->outfit->name); /* Reset timer. */ w->timer += rate_mod * outfit_delay( w->outfit ); return 1; }