Commit various options of recharging shields & energy banks, as discussed.

By default, Eric's suggestion is enabled (Case 1).  Case 0 is current
behaviour, and Case 2 is my suggestion.

Once a solution is picked, the others should be removed.


git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@3814 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Michael Werle 2010-11-14 18:40:28 +00:00
parent b0b182153b
commit 0266a49b78
2 changed files with 175 additions and 31 deletions

View File

@ -42,6 +42,13 @@
//hyperspace_tunnel_color_1 = (1.0, 0.0, 0.0, 0.5); // fallback value, same as docking tunnel
//hyperspace_tunnel_color_2 = (0.0, 0.0, 1.0, 0.25); // fallback value, same as docking tunnel
/* This setting controls the minimum charge level of the energy banks
before the shields start charging. It's taken as a percentage value
from 0.0 (0%) to 1.0 (100%). If the energy banks are less than this,
energy is first used to charge the banks, and only then the shields.
Default: 0.0
*/
//shield_charge_energybank_threshold = 0.75;
/* Worlds with "pink oceans" or "vast oceans" according to system
description. "Unusual oceans" are ignored.

View File

@ -1575,6 +1575,12 @@ static GLfloat sBaseMass = 0.0;
STAGE_TRACKING_END
}
// TODO - remove (testing only)
static int EnergyDistribution = 1; // NB: Only initialised once; set via debugger
#if !defined(NDEBUG)
static float minShieldLevelPercentage = 1.00; // 0 .. 1
static bool minShieldLevelPercentageInitialised = false;
#endif
- (void) doBookkeeping:(double) delta_t
{
@ -1652,6 +1658,31 @@ static GLfloat sBaseMass = 0.0;
}
}
// ecm
if (ecm_in_operation)
{
UPDATE_STAGE(@"updating ECM");
if (energy > 0.0)
energy -= (float)(ECM_ENERGY_DRAIN_FACTOR * delta_t); // drain energy because of the ECM
else
{
ecm_in_operation = NO;
[UNIVERSE addMessage:DESC(@"ecm-out-of-juice") forCount:3.0];
}
if ([UNIVERSE getTime] > ecm_start_time + ECM_DURATION)
{
ecm_in_operation = NO;
}
}
// Energy Banks and Shields
// TODO: Remove case statement once we pick the best solution.
switch(EnergyDistribution)
{
case 0:
// Current Oolite behaviour
{
UPDATE_STAGE(@"updating energy and shield charges");
if (energy < maxEnergy)
{
@ -1681,22 +1712,128 @@ static GLfloat sBaseMass = 0.0;
}
forward_shield = OOClamp_0_max_f(forward_shield, fwdMax);
aft_shield = OOClamp_0_max_f(aft_shield, aftMax);
if (ecm_in_operation)
}
break;
case 1:
/* Eric's shield-charging proposal:
1. If shields are less than a threshold, recharge with all available energy
2. If energy banks are below threshold, recharge with generated energy
3. Charge shields with any surplus energy
*/
{
UPDATE_STAGE(@"updating ECM");
UPDATE_STAGE(@"updating energy and shield charges");
if (energy > 0.0)
energy -= (float)(ECM_ENERGY_DRAIN_FACTOR * delta_t); // drain energy because of the ECM
// 1. (Over)charge energy banks (will get normalised later)
double energy_multiplier = 1.0 + 0.1 * [self installedEnergyUnitType]; // 1.8x recharge with normal energy unit, 2.6x with naval!
energy += energy_recharge_rate * energy_multiplier * delta_t;
// 2. Calculate shield recharge rates
float fwdMax = [self maxForwardShieldLevel];
float aftMax = [self maxAftShieldLevel];
float shieldRecharge = [self shieldRechargeRate] * delta_t;
float rechargeFwd = MIN(shieldRecharge, fwdMax - forward_shield);
float rechargeAft = MIN(shieldRecharge, aftMax - aft_shield);
// Note: we've simplified this a little, so if either shield is below
// the critical threshold, we allocate all energy. Ideally we
// would only allocate the full recharge to the critical shield,
// but doing so would add another few levels of if-then below.
float energyForShields = energy;
if( (forward_shield > fwdMax * 0.25) && (aft_shield > aftMax * 0.25) )
{
// TODO: Can this be cached anywhere sensibly (without adding another member variable)?
float minEnergyBankLevel = [[UNIVERSE planetInfo] oo_floatForKey:@"shield_charge_energybank_threshold" defaultValue:0.25];
energyForShields = MAX(0.0, energy -0.1 - (maxEnergy * minEnergyBankLevel)); // NB: The - 0.1 ensures the energy value does not 'bounce' across the critical energy message and causes spurious energy-low warnings
}
if( forward_shield < aft_shield )
{
rechargeFwd = MIN(rechargeFwd, energyForShields);
rechargeAft = MIN(rechargeAft, energyForShields - rechargeFwd);
}
else
{
ecm_in_operation = NO;
[UNIVERSE addMessage:DESC(@"ecm-out-of-juice") forCount:3.0];
rechargeAft = MIN(rechargeAft, energyForShields);
rechargeFwd = MIN(rechargeFwd, energyForShields - rechargeAft);
}
if ([UNIVERSE getTime] > ecm_start_time + ECM_DURATION)
// 3. Recharge shields, drain banks, and clamp values
forward_shield += rechargeFwd;
aft_shield += rechargeAft;
energy -= rechargeFwd + rechargeAft;
forward_shield = OOClamp_0_max_f(forward_shield, fwdMax);
aft_shield = OOClamp_0_max_f(aft_shield, aftMax);
energy = OOClamp_0_max_f(energy, maxEnergy);
}
break;
case 2:
/* Micha's new shield recharging based on a key:
1. Recharge energy banks
(currEnergy += generatedEnergy)
2. Calculate energy available for shields
(shieldEnergy = currEnergy - energyThreshold)
3. Distribute available energy amongst shields
*/
{
ecm_in_operation = NO;
UPDATE_STAGE(@"updating energy and shield charges");
double energy_multiplier = 1.0 + 0.1 * [self installedEnergyUnitType]; // 1.8x recharge with normal energy unit, 2.6x with naval!
float energyGenerated = energy_recharge_rate * energy_multiplier * delta_t;
// 1. (Over)charge energy banks (will get normalised later)
energy += energyGenerated;
// 2. Calculate how much energy can be used for the shields
#if defined(NDEBUG)
// TODO - cache this value somewhere, or is it cheap enough to perform this lookup?
float minEnergyBankLevel = [[UNIVERSE planetInfo] oo_floatForKey:@"shield_charge_energybank_threshold" defaultValue:0.0];
float energyForShields = MAX(0.0, energy - (maxEnergy * minEnergyBankLevel));
#else
// MKW - use static vars for debugging, since we can change them using the debugger
if( !minShieldLevelPercentageInitialised )
{
minShieldLevelPercentage = [[UNIVERSE planetInfo] oo_floatForKey:@"shield_charge_energybank_threshold" defaultValue:0.0];
minShieldLevelPercentageInitialised = true;
}
float energyForShields = MAX(0.0, energy - (maxEnergy * minShieldLevelPercentage));
#endif
// 3. Recharge shields with leftover energy; try to distribute fairly
if( energyForShields > 0.0 )
{
float fwdMax = [self maxForwardShieldLevel];
float aftMax = [self maxAftShieldLevel];
float recharge = [self shieldRechargeRate] * delta_t;
float rechargeFwd = MIN(recharge, fwdMax - forward_shield);
float rechargeAft = MIN(recharge, aftMax - aft_shield);
if( (rechargeFwd == rechargeAft) ||
((rechargeFwd > energyForShields) && (rechargeAft > energyForShields)) )
{
rechargeFwd = MIN(rechargeFwd, energyForShields / 2.0);
rechargeAft = MIN(rechargeAft, energyForShields / 2.0);
}
else if( rechargeFwd < energyForShields )
{
rechargeAft = MIN(rechargeAft, energyForShields - rechargeFwd);
}
else
{
rechargeFwd = MIN(rechargeFwd, energyForShields - rechargeAft);
}
forward_shield += rechargeFwd;
aft_shield += rechargeAft;
energy -= rechargeFwd;
energy -= rechargeAft;
forward_shield = OOClamp_0_max_f(forward_shield, fwdMax);
aft_shield = OOClamp_0_max_f(aft_shield, aftMax);
}
energy = OOClamp_0_max_f(energy, maxEnergy);
}
break;
}
if (sun)