* fix: the. shipFiredMissile event now fires for all missiles with a valid target, regardless of scanClass.

* added .shipReleasedEquipment event for all bombs/external equipment launched.

- corrected wrong faceArea calculation inside OOMesh.
- removed unused/experimental alternative shield recharge behaviours.
- Made it slightly easier for escape pods to land. Catch them while you can! :)
- rate of refuelling now dependent on ship's general state of repair. As a side effect, this also increases the refuelling price depending on state of repair, an alternative would be to decrease the max ly jump radius, while leaving the price for a full tank unmodified by repair status. Will put the question to the forum!

Plus the inevitable 'assorted code & comments cleanup'.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@4742 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Marc 2012-01-18 19:55:33 +00:00
parent deb8b846be
commit 3d0f56443a
5 changed files with 116 additions and 194 deletions

View File

@ -1679,12 +1679,6 @@ 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
{
@ -1781,165 +1775,57 @@ static bool minShieldLevelPercentageInitialised = false;
}
// Energy Banks and Shields
// TODO: Remove case statement once we pick the best solution.
switch(EnergyDistribution)
/* Shield-charging behaviour, as per Eric's 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 energy and shield charges");
// 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) )
{
case 0:
// Current Oolite behaviour
{
UPDATE_STAGE(@"updating energy and shield charges");
if (energy < maxEnergy)
{
double energy_multiplier = 1.0 + 0.1 * [self installedEnergyUnitType]; // 1.8x recharge with normal energy unit, 2.6x with naval!
energy += (float)(energy_recharge_rate * energy_multiplier * delta_t);
if (energy > maxEnergy)
energy = maxEnergy;
}
// Recharge shields from energy banks
float rechargeFwd = (float)([self shieldRechargeRate] * delta_t);
float rechargeAft = rechargeFwd;
float fwdMax = [self maxForwardShieldLevel];
float aftMax = [self maxAftShieldLevel];
if (forward_shield < fwdMax)
{
if (forward_shield + rechargeFwd > fwdMax) rechargeFwd = fwdMax - forward_shield;
forward_shield += rechargeFwd;
energy -= rechargeFwd;
}
if (aft_shield < aftMax)
{
if (aft_shield + rechargeAft > aftMax) rechargeAft = aftMax - aft_shield;
aft_shield += rechargeAft;
energy -= rechargeAft;
}
forward_shield = OOClamp_0_max_f(forward_shield, fwdMax);
aft_shield = OOClamp_0_max_f(aft_shield, aftMax);
}
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 energy and shield charges");
// 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
{
rechargeAft = MIN(rechargeAft, energyForShields);
rechargeFwd = MIN(rechargeFwd, energyForShields - rechargeAft);
}
// 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
*/
{
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;
// 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
{
rechargeAft = MIN(rechargeAft, energyForShields);
rechargeFwd = MIN(rechargeFwd, energyForShields - rechargeAft);
}
// 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);
if (sun)
{
UPDATE_STAGE(@"updating sun effects");
@ -2504,7 +2390,7 @@ static bool minShieldLevelPercentageInitialised = false;
}
else
{
// FIXME: how to preload target system for galactic jump?
// FIXME: preload target system for galactic jump?
}
UPDATE_STAGE(@"JUMP!");
@ -2636,6 +2522,8 @@ static bool minShieldLevelPercentageInitialised = false;
[UNIVERSE displayMessage:scoreMS forCount:kDeadResetTime];
[UNIVERSE displayMessage:@"" forCount:kDeadResetTime];
[UNIVERSE displayMessage:ExpandDescriptionForCurrentSystem(@"[gameoverscreen-press-space]") forCount:kDeadResetTime];
[UNIVERSE displayMessage:@" " forCount:kDeadResetTime];
[UNIVERSE displayMessage:@"" forCount:kDeadResetTime];
[self resetShotTime];
}
@ -6608,16 +6496,44 @@ static NSString *last_outfitting_key=nil;
if (justCobra)
{
text = DESC(@"game-copyright");
[gui setText:text forRow:17 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor whiteColor] forRow:17];
[gui setText:text forRow:15 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor whiteColor] forRow:15];
text = DESC(@"theme-music-credit");
[gui setText:text forRow:19 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor grayColor] forRow:19];
[gui setText:text forRow:17 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor grayColor] forRow:17];
text = DESC(@"load-previous-commander");
[gui setText:text forRow:21 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor yellowColor] forRow:21];
// Ask to load previous commander only if we have at least one previous commander to load.
NSFileManager *saveFileManager = [NSFileManager defaultManager];
NSArray *cdrArray = [saveFileManager commanderContentsOfPath: [[UNIVERSE gameController] playerFileDirectory]];
unsigned j;
BOOL fileExists, isDir, oneCdr = NO;
for(j = 0; j < [cdrArray count] && !oneCdr; j++)
{
NSString* path = [cdrArray objectAtIndex:j];
fileExists = [saveFileManager fileExistsAtPath:path isDirectory:&isDir];
if (fileExists && !isDir && [[[path pathExtension] lowercaseString] isEqualToString:@"oolite-save"])
{
oneCdr = YES;
}
}
if (oneCdr)
{
text = DESC(@"load-previous-commander");
[gui setText:text forRow:19 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor yellowColor] forRow:19];
}
else
{
text = DESC(@"press-space-commander");
[gui setText:text forRow:21 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor yellowColor] forRow:21];
justCobra = NO;
}
// check for error messages from Resource Manager
[ResourceManager paths];
@ -8442,15 +8358,13 @@ static NSString *last_outfitting_key=nil;
if (![UNIVERSE strict])
{
rate = [super fuelChargeRate];
#if 0
// post-NMSR fuelPrices - the state of repair to affect the rate?
// state of repair never lower than 75, but added the check just in case. -- Kaks 20110429
// Experimental: the state of repair affects the fuel charge rate - more fuel needed for jumps, etc...
if (EXPECT(ship_trade_in_factor <= 90 && ship_trade_in_factor >= 75))
{
rate *= 2.0 - (ship_trade_in_factor / 100); // between 1.1x and 1.25x
OOLog(@"fuelPrices", @"\"%@\" - repair status: %d%%, adjusted rate to:%.2f)", [self shipDataKey], ship_trade_in_factor, rate);
//OOLog(@"fuelPrices", @"\"%@\" - repair status: %d%%, adjusted rate to:%.2f)", [self shipDataKey], ship_trade_in_factor, rate);
}
#endif
}
return rate;
}

View File

@ -1432,9 +1432,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
- (void) awardFuel:(NSString *)valueString // add to fuel up to 7.0 LY
{
// all awardFuel calls from OXPs will potentially award the wrong fuel amount if multiplied by fuelChargeRate.
int delta = 10 * [valueString floatValue];
// int delta = 10 * [valueString floatValue] * [scriptTarget fuelChargeRate];
OOFuelQuantity scriptTargetFuelBeforeAward = [scriptTarget fuel];
if (delta < 0 && scriptTargetFuelBeforeAward < (unsigned)-delta) [scriptTarget setFuel:0];

View File

@ -5375,15 +5375,12 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
GLfloat rate = 1.0; // Standard (& strict play) charge rate.
#if MASS_DEPENDENT_FUEL_PRICES
// Fuel scooping and prices are relative to the mass of the cobra3.
// Post MNSR it's also going to be affected by missing subents, and possibly repair status.
// N.B. "fuel_charge_rate" now fully removed, in favour of a dynamic system. -- Kaks 20110429
if (![UNIVERSE strict])
{
if (EXPECT(PLAYER != nil && mass> 0 && mass != [PLAYER baseMass]))
{
rate = calcFuelChargeRate(mass); // post-MNSR fuelPrices will be affected by missing subents. see [self subEntityDied]
rate = calcFuelChargeRate(mass);
}
}
OOLog(@"fuelPrices", @"\"%@\" fuel charge rate: %.2f (mass ratio: %.2f/%.2f)", [self shipDataKey], rate, mass, [PLAYER baseMass]);
@ -6236,11 +6233,9 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
if ([self subEntityTakingDamage] == sub) [self setSubEntityTakingDamage:nil];
[sub setOwner:nil];
#if 0
// TODO? Recalculating collision radius should increase collision testing efficiency,
// but for most ship models the difference would be marginal. -- Kaks 20110429
mass -= [sub mass]; // post-NMSR fuelPrices - missing subents will affect fuel charge rate
#endif
mass -= [sub mass]; // missing subents affect fuel charge rate, etc..
[subEntities removeObject:sub];
}
@ -8042,13 +8037,17 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
[missile release]; //release
// missile lives on after UNIVERSE addEntity
if ([missile scanClass] == CLASS_MISSILE && [target isShip])
if ([missile isMissile] && [target isShip])
{
[self doScriptEvent:OOJSID("shipFiredMissile") withArgument:missile andArgument:target_ship];
[target_ship setPrimaryAggressor:self];
[target_ship doScriptEvent:OOJSID("shipAttackedWithMissile") withArgument:missile andArgument:self];
[target_ship reactToAIMessage:@"INCOMING_MISSILE" context:@"hay guise, someone's shooting at me!"];
}
else
{
[self doScriptEvent:OOJSID("shipReleasedEquipment") withArgument:missile andArgument:self];
}
if (cloaking_device_active && cloakPassive)
{
@ -8728,7 +8727,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
[cargo insertObject:other atIndex:0]; // places most recently scooped object at eject position
[other setStatus:STATUS_IN_HOLD];
[other setBehaviour:BEHAVIOUR_TUMBLE];
// [self doScriptEvent:OOJSID("cargoScooped") withArguments:[NSArray arrayWithObjects:CommodityTypeToString(co_type), [NSNumber numberWithInt:co_amount], nil]]; //post-MNSR - add cargoScooped() event
[self doScriptEvent:OOJSID("cargoScooped") withArguments:[NSArray arrayWithObjects:CommodityTypeToString(co_type), [NSNumber numberWithInt:co_amount], nil]];
[shipAI message:@"CARGO_SCOOPED"];
if (max_cargo && [cargo count] >= max_cargo) [shipAI message:@"HOLD_FULL"];
}
@ -9376,14 +9375,13 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
This function causes problems with Thargoids: their missiles (aka Thargons) are automatically
added to the escorts group, and when a mother ship dies all thargons will attach themselves
as escorts to the surviving battleships. This can lead to huge escort groups.
Post-MNSR TODO: better handling of Thargoid groups.
TODO: better handling of Thargoid groups:
- put thargons (& all other thargon missiles) in their own non-escort group perhaps?
*/
// The _escortPositions array size is always MAX_ESCORTS, so clamp max idx.
// this now returns the same last escort position for all escorts above MAX_ESCORTS
// The _escortPositions array is always MAX_ESCORTS long.
// Kludge: return the same last escort position if we have escorts above MAX_ESCORTS...
idx = MIN(idx, (unsigned)(MAX_ESCORTS - 1));
//NSParameterAssert(idx < MAX_ESCORTS);
return vector_add(self->position, quaternion_rotate_vector([self normalOrientation], _escortPositions[idx]));
}

View File

@ -850,7 +850,7 @@ MA 02110-1301, USA.
if (the_planet)
{
Vector p_pos = the_planet->position;
double p_cr = the_planet->collision_radius; // 200m above the surface
double p_cr = the_planet->collision_radius; // the surface
Vector p1 = vector_between(p_pos, position);
p1 = vector_normal(p1); // vector towards ship
p1.x += 0.5 * (randf() - 0.5);
@ -858,7 +858,7 @@ MA 02110-1301, USA.
p1.z += 0.5 * (randf() - 0.5);
p1 = vector_normal(p1);
destination = make_vector(p_pos.x + p1.x * p_cr, p_pos.y + p1.y * p_cr, p_pos.z + p1.z * p_cr); // on surface
desired_range = collision_radius + 50.0; // +50m from the destination
desired_range = collision_radius + 100.0; // +100m from the destination
}
else
{

View File

@ -1671,6 +1671,17 @@ shaderBindingTarget:(id<OOWeakReferenceSupport>)target
}
static float FaceArea(GLuint *vertIndices, Vector *vertices)
{
/* Calculate areas using Heron's formula. */
float a2 = distance2(vertices[vertIndices[0]], vertices[vertIndices[1]]);
float b2 = distance2(vertices[vertIndices[1]], vertices[vertIndices[2]]);
float c2 = distance2(vertices[vertIndices[2]], vertices[vertIndices[0]]);
return sqrtf((2.0 * (a2 * b2 + b2 * c2 + c2 * a2) - (a2 * a2 + b2 * b2 +c2 * c2)) * 0.0625);
}
#if 0
static float FaceAreaBroken(GLuint *vertIndices, Vector *vertices)
{
/* This is supposed to calculate areas using Heron's formula, but doesn't.
@ -1687,6 +1698,7 @@ static float FaceAreaBroken(GLuint *vertIndices, Vector *vertices)
float c2 = distance2(vertices[vertIndices[2]], vertices[vertIndices[0]]);
return sqrtf(2.0 * (a2 * b2 + b2 * c2 + c2 * a2) - 0.25 * (a2 * a2 + b2 * b2 +c2 * c2));
}
#endif
- (void) calculateVertexNormalsAndTangentsWithFaceRefs:(VertexFaceRef *)faceRefs
@ -1702,7 +1714,7 @@ static float FaceAreaBroken(GLuint *vertIndices, Vector *vertices)
for (i = 0 ; i < faceCount; i++)
{
triangle_area[i] = FaceAreaBroken(_faces[i].vertex, _vertices);
triangle_area[i] = FaceArea(_faces[i].vertex, _vertices);
}
for (i = 0; i < vertexCount; i++)
{
@ -1810,7 +1822,7 @@ static float FaceAreaCorrect(GLuint *vertIndices, Vector *vertices)
{
if ((_faces[j].vertex[0] == v_index)||(_faces[j].vertex[1] == v_index)||(_faces[j].vertex[2] == v_index))
{
float area = FaceAreaBroken(_faces[j].vertex, _vertices);
float area = FaceArea(_faces[j].vertex, _vertices);
normal_sum = vector_add(normal_sum, vector_multiply_scalar(_faces[j].normal, area));
tangent_sum = vector_add(tangent_sum, vector_multiply_scalar(_faces[j].tangent, area));
}