# bobbens/naev forked from naev/naev

Switch branches/tags
Nothing to show
Fetching contributors…
Cannot retrieve contributors at this time
287 lines (239 sloc) 6.74 KB
 /* * See Licensing and Copyright notice in naev.h */ /** * @file pilot_heat.c * * @brief Handles the pilot heat stuff. */ #include "pilot_heat.h" #include "naev.h" #include #include "log.h" /** * @brief Calculates the heat parameters for a pilot. * * We treat the ship as more or less a constant slab of steel. * * @param p Pilot to update heat properties of. */ void pilot_heatCalc( Pilot *p ) { double mass_kg; mass_kg = 1000. * p->base_mass; p->heat_emis = 0.8; /**< @TODO make it influencable. */ p->heat_cond = STEEL_HEAT_CONDUCTIVITY; p->heat_C = STEEL_HEAT_CAPACITY * mass_kg; /* We'll approximate area for a sphere. * * Sphere: * V = 4/3*pi*r^3 * A = 4*pi*r^2 * * Ship: * V = mass/density * * We then equal the ship V and sphere V to obtain r: * r = (3*mass)/(4*pi*density))^(1/3) * * Substituting r in A we get: * A = 4*pi*((3*mass)/(4*pi*density))^(2/3) * */ p->heat_area = 4.*M_PI*pow( 3./4.*mass_kg/STEEL_DENSITY/M_PI, 2./3. ) * p->stats.heat_dissipation; } /** * @brief Calculates the thermal mass of an outfit. */ double pilot_heatCalcOutfitC( const Outfit *o ) { /* Simple thermal mass. */ return STEEL_HEAT_CAPACITY * 1000. * o->mass; } /** * @brief Calculates the effective transfer area of an outfit. * * @note This is currently independent of ship mounting. */ double pilot_heatCalcOutfitArea( const Outfit *o ) { double mass_kg = 1000. * o->mass; /* We consider the effective area of outfits to be half of a sphere. */ return 2.*M_PI*pow( 3./4.*mass_kg/STEEL_DENSITY/M_PI, 2./3. ); } /** * @brief Calculates the heat parameters for a pilot's slot. */ void pilot_heatCalcSlot( PilotOutfitSlot *o ) { o->heat_T = CONST_SPACE_STAR_TEMP; /* Reset temperature. */ o->heat_start = CONST_SPACE_STAR_TEMP; /* For cooldown purposes. */ if (o->outfit == NULL) { o->heat_C = 1.; o->heat_area = 0.; return; } o->heat_C = pilot_heatCalcOutfitC( o->outfit ); o->heat_area = pilot_heatCalcOutfitArea( o->outfit ); } /** * @brief Resets a pilot's heat. * * @param p Pilot to reset heat of. */ void pilot_heatReset( Pilot *p ) { int i; p->heat_T = CONST_SPACE_STAR_TEMP; for (i=0; inoutfits; i++) p->outfits[i]->heat_T = CONST_SPACE_STAR_TEMP; } /** * @brief Adds heat to an outfit slot. * * @param p Pilot whose slot it is. * @param o The slot in question. */ void pilot_heatAddSlot( Pilot *p, PilotOutfitSlot *o ) { double hmod; /* We consider that only 1% of the energy is lost in the form of heat, * this keeps numbers sane. */ if (o->outfit->type == OUTFIT_TYPE_BOLT) hmod = p->stats.fwd_heat; else if (o->outfit->type == OUTFIT_TYPE_TURRET_BOLT) hmod = p->stats.tur_heat; else hmod = 1.; o->heat_T += hmod * outfit_heat(o->outfit) / o->heat_C; /* Enforce a minimum value as a safety measure. */ o->heat_T = MAX( o->heat_T, CONST_SPACE_STAR_TEMP ); } /** * @brief Adds heat to an outfit slot over a period of time. * * @param p Pilot whose slot it is. * @param o The slot in question. * @param dt Delta tick. */ void pilot_heatAddSlotTime( Pilot *p, PilotOutfitSlot *o, double dt ) { (void) p; double hmod; /* @todo Handle beam modifiers for ships here. */ hmod = 1.; o->heat_T += (hmod * outfit_heat(o->outfit) / o->heat_C) * dt; /* Enforce a minimum value as a safety measure. */ o->heat_T = MAX( o->heat_T, CONST_SPACE_STAR_TEMP ); } /** * @brief Heats the pilot's slot. * * We only consider conduction with the ship's chassis. * * q = -k * dT/dx * * q being heat flux W/m^2 * k being conductivity W/(m*K) * dT/dx temperature gradient along one dimension K/m * * Slots are connected only with the chassis. * * @param p Pilot to update. * @param o Outfit slot to update. * @param dt Delta tick. * @return The energy transferred. */ double pilot_heatUpdateSlot( Pilot *p, PilotOutfitSlot *o, double dt ) { double Q; /* Calculate energy leaving/entering ship chassis. */ Q = -p->heat_cond * (o->heat_T - p->heat_T) * o->heat_area * dt; /* Update current temperature. */ o->heat_T += Q / o->heat_C; /* Return energy moved. */ return Q; } /** * @brief Heats the pilot's ship. * * The ship besides having conduction like in pilot_heatUpdateSlot it also has * radiation. So now the equation we use is: * * q = -k * dT/dx + sigma * epsilon * (T^4 - To^4) * * However the first part is passed as parameter p so we get: * * q = p + sigma * epsilon * (T^4 - To^4) * * sigma being the Stefan-Boltzmann constant [5] = 5.67×10−8 W/(m^2 K^4) * epsilon being a parameter between 0 and 1 (1 being black body) * T being body temperature * To being "space temperature" * * @param p Pilot to update. * @param Q Heat energy moved from slots. * @param dt Delta tick. */ void pilot_heatUpdateShip( Pilot *p, double Q_cond, double dt ) { double Q, Q_rad; /* Calculate radiation. */ Q_rad = CONST_STEFAN_BOLTZMANN * p->heat_area * p->heat_emis * (CONST_SPACE_STAR_TEMP_4 - pow(p->heat_T,4.)) * dt; /* Total heat movement. */ Q = Q_rad - Q_cond; /* Update ship temperature. */ p->heat_T += Q / p->heat_C; } /** * @brief Returns a 0:1 modifier representing efficiency (1. being normal). * * @param T Actual temperature (K) * @param Tb Base temperature for overheating purposes (K) * @param Tc Max temperature for overheating purposes (K) */ double pilot_heatEfficiencyMod( double T, double Tb, double Tc ) { return CLAMP( 0., 1., 1 - (T - Tb) / Tc ); } /** * @brief Overrides the usual heat model during active cooldown. * * @param p Pilot to update. * @param dt Delta tick. */ void pilot_heatUpdateCooldown( Pilot *p ) { double t; int i; PilotOutfitSlot *o; t = pow2( 1. - p->ctimer / p->cdelay ); p->heat_T = p->heat_start - CONST_SPACE_STAR_TEMP - (p->heat_start - CONST_SPACE_STAR_TEMP) * t + CONST_SPACE_STAR_TEMP; for (i=0; inoutfits; i++) { o = p->outfits[i]; o->heat_T = o->heat_start - CONST_SPACE_STAR_TEMP - (o->heat_start - CONST_SPACE_STAR_TEMP) * t + CONST_SPACE_STAR_TEMP; } } /** * @brief Returns a 0:1 modifier representing accuracy (0. being normal). */ double pilot_heatAccuracyMod( double T ) { return CLAMP( 0., 1., (T-500.)/600. ); } /** * @brief Returns a 0:1 modifier representing fire rate (1. being normal). */ double pilot_heatFireRateMod( double T ) { return CLAMP( 0., 1., (1100.-T)/300. ); } /** * @brief Returns a 0:2 level of fire, 0:1 is the accuracy point, 1:2 is fire rate point. */ double pilot_heatFirePercent( double T ) { return 2*pilot_heatAccuracyMod(T); }