/** * @brief Throws cargo out in space graphically. * * @param pilot ID of the pilot throwing the stuff out * @param com Commodity to throw out. * @param quantity Quantity thrown out. */ void commodity_Jettison( int pilot, Commodity* com, int quantity ) { (void)com; int i; Pilot* p; int n, effect; double px,py, bvx, bvy, r,a, vx,vy; p = pilot_get( pilot ); n = MAX( 1, RNG(quantity/10, quantity/5) ); px = p->solid->pos.x; py = p->solid->pos.y; bvx = p->solid->vel.x; bvy = p->solid->vel.y; for (i=0; i<n; i++) { effect = spfx_get("cargo"); /* Radial distribution gives much nicer results */ r = RNGF()*25 - 12.5; a = 2. * M_PI * RNGF(); vx = bvx + r*cos(a); vy = bvy + r*sin(a); /* Add the cargo effect */ spfx_add( effect, px, py, vx, vy, SPFX_LAYER_BACK ); } }
/** * @brief Does explosion in a radius (damage and graphics). * * @param x X position of explosion center. * @param y Y position of explosion center. * @param vx X velocity of explosion center. * @param vy Y velocity of explosion center. * @param radius Radius of the explosion. * @param dtype Damage type. * @param damage Damage amount. * @param parent Parent of the explosion, NULL is none. * @param mode Defines the explosion behaviour. */ void expl_explode( double x, double y, double vx, double vy, double radius, const Damage *dmg, const Pilot *parent, int mode ) { int i, n; double a, d; double area; double ex, ey; int layer; int efx; /* Standard stuff - lazy allocation. */ if (exp_s == -1) { exp_s = spfx_get("ExpS"); exp_m = spfx_get("ExpM"); exp_l = spfx_get("ExpL"); } layer = SPFX_LAYER_FRONT; /* Number of explosions. */ area = M_PI * pow2(radius); n = (int)(area / 100.); /* Create explosions. */ for (i=0; i<n; i++) { /* Get position. */ a = RNGF()*360.; d = RNGF()*(radius-5.) + 5.; ex = d*cos(a); ey = d*sin(a); /* Create explosion. */ efx = (RNG(0,2)==0) ? exp_m : exp_s; spfx_add( efx, x+ex, y+ey, vx, vy, layer ); } /* Final explosion. */ spfx_add( exp_l, x, y, vx, vy, layer ); /* Run the damage. */ if (dmg != NULL) expl_explodeDamage( x, y, radius, dmg, parent, mode ); }
/** * @brief Weapon hit the pilot. * * @param w Weapon involved in the collision. * @param p Pilot that got hit. * @param layer Layer to which the weapon belongs. * @param pos Position of the hit. * @param dt Current delta tick. */ static void weapon_hitBeam( Weapon* w, Pilot* p, WeaponLayer layer, Vector2d pos[2], const double dt ) { (void) layer; Pilot *parent; int spfx; double damage; DamageType dtype; WeaponLayer spfx_layer; /* Get general details. */ parent = pilot_get(w->parent); damage = outfit_damage(w->outfit) * dt; dtype = outfit_damageType(w->outfit); /* Have pilot take damage and get real damage done. */ damage = pilot_hit( p, w->solid, w->parent, dtype, damage ); /* Add sprite, layer depends on whether player shot or not. */ if (w->lockon == -1.) { /* Get the layer. */ spfx_layer = (p==player) ? SPFX_LAYER_FRONT : SPFX_LAYER_BACK; /* Choose spfx. */ if (p->shield > 0.) spfx = outfit_spfxShield(w->outfit); else spfx = outfit_spfxArmour(w->outfit); /* Add graphic. */ spfx_add( spfx, pos[0].x, pos[0].y, VX(p->solid->vel), VY(p->solid->vel), spfx_layer ); spfx_add( spfx, pos[1].x, pos[1].y, VX(p->solid->vel), VY(p->solid->vel), spfx_layer ); w->lockon = -2; } /* Inform AI that it's been hit. */ weapon_hitAI( p, parent, damage ); }
/** * @brief Weapon hit the pilot. * * @param w Weapon involved in the collision. * @param p Pilot that got hit. * @param layer Layer to which the weapon belongs. * @param pos Position of the hit. */ static void weapon_hit( Weapon* w, Pilot* p, WeaponLayer layer, Vector2d* pos ) { Pilot *parent; int spfx; double damage; DamageType dtype; WeaponLayer spfx_layer; int s; /* Get general details. */ parent = pilot_get(w->parent); damage = w->strength * outfit_damage(w->outfit); dtype = outfit_damageType(w->outfit); /* Play sound if they have it. */ s = outfit_soundHit(w->outfit); if (s != -1) w->voice = sound_playPos( s, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y); /* Have pilot take damage and get real damage done. */ damage = pilot_hit( p, w->solid, w->parent, dtype, damage ); /* Get the layer. */ spfx_layer = (p==player) ? SPFX_LAYER_FRONT : SPFX_LAYER_BACK; /* Choose spfx. */ if (p->shield > 0.) spfx = outfit_spfxShield(w->outfit); else spfx = outfit_spfxArmour(w->outfit); /* Add sprite, layer depends on whether player shot or not. */ spfx_add( spfx, pos->x, pos->y, VX(p->solid->vel), VY(p->solid->vel), spfx_layer ); /* Inform AI that it's been hit. */ weapon_hitAI( p, parent, damage ); /* no need for the weapon particle anymore */ weapon_destroy(w,layer); }
/** * @brief Updates all the weapons in the layer. * * @param dt Current delta tick. * @param layer Layer to update. */ static void weapons_updateLayer( const double dt, const WeaponLayer layer ) { Weapon **wlayer; int *nlayer; Weapon *w; int i; int spfx; int s; /* Choose layer. */ switch (layer) { case WEAPON_LAYER_BG: wlayer = wbackLayer; nlayer = &nwbackLayer; break; case WEAPON_LAYER_FG: wlayer = wfrontLayer; nlayer = &nwfrontLayer; break; default: WARN("Unknown weapon layer!"); } i = 0; while (i < *nlayer) { w = wlayer[i]; switch (w->outfit->type) { /* most missiles behave the same */ case OUTFIT_TYPE_AMMO: case OUTFIT_TYPE_TURRET_AMMO: if (w->lockon > 0.) /* decrement lockon */ w->lockon -= dt; limit_speed( &w->solid->vel, w->outfit->u.amm.speed, dt ); w->timer -= dt; if (w->timer < 0.) { spfx = -1; /* See if we need armour death sprite. */ if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR)) spfx = outfit_spfxArmour(w->outfit); /* See if we need shield death sprite. */ else if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD)) spfx = outfit_spfxShield(w->outfit); /* Add death sprite if needed. */ if (spfx != -1) { spfx_add( spfx, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y, SPFX_LAYER_BACK ); /* presume back. */ /* Add sound if explodes and has it. */ s = outfit_soundHit(w->outfit); if (s != -1) w->voice = sound_playPos(s, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y); } weapon_destroy(w,layer); break; } break; case OUTFIT_TYPE_BOLT: case OUTFIT_TYPE_TURRET_BOLT: w->timer -= dt; if (w->timer < 0.) { spfx = -1; /* See if we need armour death sprite. */ if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR)) spfx = outfit_spfxArmour(w->outfit); /* See if we need shield death sprite. */ else if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD)) spfx = outfit_spfxShield(w->outfit); /* Add death sprite if needed. */ if (spfx != -1) { spfx_add( spfx, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y, SPFX_LAYER_BACK ); /* presume back. */ /* Add sound if explodes and has it. */ s = outfit_soundHit(w->outfit); if (s != -1) w->voice = sound_playPos(s, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y); } weapon_destroy(w,layer); break; } else if (w->timer < w->falloff) w->strength = w->timer / w->falloff; break; /* Beam weapons handled a part. */ case OUTFIT_TYPE_BEAM: case OUTFIT_TYPE_TURRET_BEAM: w->timer -= dt; if (w->timer < 0.) { weapon_destroy(w,layer); break; } /* We use the lockon to tell when we have to create explosions. */ w->lockon -= dt; if (w->lockon < 0.) { if (w->lockon < -1.) w->lockon = 0.100; else w->lockon = -1.; } break; default: WARN("Weapon of type '%s' has no update implemented yet!", w->outfit->name); break; } /* Out of bounds, loop is over. */ if (i >= *nlayer) break; /* Only increment if weapon wasn't deleted. */ if (w == wlayer[i]) { weapon_update(w,dt,layer); if ((i < *nlayer) && (w == wlayer[i])) i++; } } }