Permalink
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 <math.h>
#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; i<p->noutfits; 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; i<p->noutfits; 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);
}