/** * @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 Parses the beam weapon specifics of an outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSBeam( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr node; /* Defaults. */ temp->u.bem.spfx_armour = -1; temp->u.bem.spfx_shield = -1; temp->u.bem.sound_warmup = -1; temp->u.bem.sound = -1; temp->u.bem.sound_off = -1; node = parent->xmlChildrenNode; do { /* load all the data */ xmlr_float(node,"range",temp->u.bem.range); xmlr_float(node,"turn",temp->u.bem.turn); xmlr_float(node,"energy",temp->u.bem.energy); xmlr_long(node,"delay",temp->u.bem.delay); xmlr_float(node,"warmup",temp->u.bem.warmup); xmlr_float(node,"duration",temp->u.bem.duration); if (xml_isNode(node,"damage")) { outfit_parseDamage( &temp->u.bem.dtype, &temp->u.bem.damage, node ); continue; } /* Graphic stuff. */ if (xml_isNode(node,"gfx")) { temp->u.bem.gfx = xml_parseTexture( node, OUTFIT_GFX"space/%s.png", 1, 1, 0 ); continue; } if (xml_isNode(node,"spfx_armour")) { temp->u.bem.spfx_armour = spfx_get(xml_get(node)); continue; } if (xml_isNode(node,"spfx_shield")) { temp->u.bem.spfx_shield = spfx_get(xml_get(node)); continue; } /* Sound stuff. */ if (xml_isNode(node,"sound_warmup")) { temp->u.bem.sound_warmup = sound_get( xml_get(node) ); continue; } if (xml_isNode(node,"sound")) { temp->u.bem.sound = sound_get( xml_get(node) ); continue; } if (xml_isNode(node,"sound_off")) { temp->u.bem.sound_off = sound_get( xml_get(node) ); continue; } } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->u.bem.gfx==NULL,"gfx"); MELEMENT(temp->u.bem.spfx_shield==-1,"spfx_shield"); MELEMENT(temp->u.bem.spfx_armour==-1,"spfx_armour"); MELEMENT((sound_disabled!=0) && (temp->u.bem.warmup > 0.) && (temp->u.bem.sound<0),"sound_warmup"); MELEMENT((sound_disabled!=0) && (temp->u.bem.sound<0),"sound"); MELEMENT((sound_disabled!=0) && (temp->u.bem.sound_off<0),"sound_off"); MELEMENT(temp->u.bem.delay==0,"delay"); MELEMENT(temp->u.bem.duration==0,"duration"); MELEMENT(temp->u.bem.range==0,"range"); MELEMENT((temp->type!=OUTFIT_TYPE_BEAM) && (temp->u.bem.turn==0),"turn"); MELEMENT(temp->u.bem.energy==0,"energy"); MELEMENT(temp->u.bem.damage==0,"damage"); #undef MELEMENT }
/** * @brief Parses the specific area for a weapon and loads it into Outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSAmmo( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr node; char *buf; node = parent->xmlChildrenNode; /* Defaults. */ temp->u.amm.spfx_armour = -1; temp->u.amm.spfx_shield = -1; temp->u.amm.sound = -1; do { /* load all the data */ /* Basic */ xmlr_float(node,"duration",temp->u.amm.duration); xmlr_float(node,"lockon",temp->u.amm.lockon); xmlr_float(node,"resist",temp->u.amm.resist); /* Movement */ xmlr_float(node,"thrust",temp->u.amm.thrust); xmlr_float(node,"turn",temp->u.amm.turn); xmlr_float(node,"speed",temp->u.amm.speed); xmlr_float(node,"accuracy",temp->u.amm.accuracy); xmlr_float(node,"energy",temp->u.amm.energy); if (xml_isNode(node,"gfx")) { temp->u.amm.gfx_space = xml_parseTexture( node, OUTFIT_GFX"space/%s.png", 6, 6, OPENGL_TEX_MAPTRANS ); xmlr_attr(node, "spin", buf); if (buf != NULL) { outfit_setProp( temp, OUTFIT_PROP_WEAP_SPIN ); temp->u.blt.spin = atof( buf ); free(buf); } continue; } else if (xml_isNode(node,"spfx_armour")) temp->u.amm.spfx_armour = spfx_get(xml_get(node)); else if (xml_isNode(node,"spfx_shield")) temp->u.amm.spfx_shield = spfx_get(xml_get(node)); else if (xml_isNode(node,"sound")) temp->u.amm.sound = sound_get( xml_get(node) ); else if (xml_isNode(node,"damage")) outfit_parseDamage( &temp->u.amm.dtype, &temp->u.amm.damage, node ); } while (xml_nextNode(node)); /* Post-processing */ temp->u.amm.resist /= 100.; /* Set it in per one */ #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->u.amm.gfx_space==NULL,"gfx"); MELEMENT(temp->u.amm.spfx_shield==-1,"spfx_shield"); MELEMENT(temp->u.amm.spfx_armour==-1,"spfx_armour"); MELEMENT((sound_disabled!=0) && (temp->u.amm.sound<0),"sound"); /* MELEMENT(temp->u.amm.thrust==0,"thrust"); */ /* Dumb missiles don't need everything */ if (outfit_isSeeker(temp)) { MELEMENT(temp->u.amm.turn==0,"turn"); MELEMENT(temp->u.amm.lockon==0,"lockon"); } MELEMENT(temp->u.amm.speed==0,"speed"); MELEMENT(temp->u.amm.duration==0,"duration"); MELEMENT(temp->u.amm.damage==0,"damage"); #undef MELEMENT }
/** * @brief Parses the specific area for a bolt weapon and loads it into Outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSBolt( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr node; char *buf; /* Defaults */ temp->u.blt.spfx_armour = -1; temp->u.blt.spfx_shield = -1; temp->u.blt.sound = -1; node = parent->xmlChildrenNode; do { /* load all the data */ xmlr_float(node,"speed",temp->u.blt.speed); xmlr_float(node,"delay",temp->u.blt.delay); xmlr_float(node,"range",temp->u.blt.range); xmlr_float(node,"accuracy",temp->u.blt.accuracy); xmlr_float(node,"energy",temp->u.blt.energy); if (xml_isNode(node,"gfx")) { temp->u.blt.gfx_space = xml_parseTexture( node, OUTFIT_GFX"space/%s.png", 6, 6, OPENGL_TEX_MAPTRANS ); xmlr_attr(node, "spin", buf); if (buf != NULL) { outfit_setProp( temp, OUTFIT_PROP_WEAP_SPIN ); temp->u.blt.spin = atof( buf ); free(buf); } continue; } if (xml_isNode(node,"spfx_shield")) { temp->u.blt.spfx_shield = spfx_get(xml_get(node)); continue; } if (xml_isNode(node,"spfx_armour")) { temp->u.blt.spfx_armour = spfx_get(xml_get(node)); continue; } if (xml_isNode(node,"sound")) { temp->u.blt.sound = sound_get( xml_get(node) ); continue; } if (xml_isNode(node,"damage")) { outfit_parseDamage( &temp->u.blt.dtype, &temp->u.blt.damage, node ); continue; } } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->u.blt.gfx_space==NULL,"gfx"); MELEMENT(temp->u.blt.spfx_shield==-1,"spfx_shield"); MELEMENT(temp->u.blt.spfx_armour==-1,"spfx_armour"); MELEMENT((sound_disabled!=0) && (temp->u.blt.sound<0),"sound"); MELEMENT(temp->u.blt.delay==0,"delay"); MELEMENT(temp->u.blt.speed==0,"speed"); MELEMENT(temp->u.blt.range==0,"range"); MELEMENT(temp->u.blt.accuracy==0,"accuracy"); MELEMENT(temp->u.blt.damage==0,"damage"); #undef MELEMENT }