Added code to avoid probable cause of STATUS_DEAD ghost ships, and moar code to catch them if they appear anyway. (Bug #16624)

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2927 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2010-01-03 12:46:16 +00:00
parent 86d0553639
commit 6ba078a08e
3 changed files with 105 additions and 80 deletions

View File

@ -331,7 +331,7 @@ static OOSoundSource *sAfterburnerSources[2];
// time delay method for playing afterburner sounds
// this overlaps two sounds each 2 seconds long, but with a .5s
// this overlaps two sounds each 2 seconds long, but with a 0.75s
// crossfade
- (void) updateAfterburnerSound
{

View File

@ -5682,86 +5682,90 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
if ([self status] == STATUS_DEAD) return;
[self setStatus:STATUS_DEAD];
//scripting
if (script != nil)
{
[[PlayerEntity sharedPlayer] setScriptTarget:self];
[self doScriptEvent:@"shipDied"]; // FIXME: params missing
}
// two parts to the explosion:
// 1. fast sparks
float how_many = factor;
while (how_many > 0.5f)
{
fragment = [[ParticleEntity alloc] initFragburstSize: collision_radius fromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
how_many -= 1.0f;
}
// 2. slow clouds
how_many = factor;
while (how_many > 0.5f)
{
fragment = [[ParticleEntity alloc] initBurst2Size: collision_radius fromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
how_many -= 1.0f;
}
// we need to throw out cargo at this point.
unsigned cargo_chance = 10;
if ([[name lowercaseString] rangeOfString:@"medical"].location != NSNotFound)
{
cargo_to_go = max_cargo * cargo_chance / 100;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
[self setCargo:[UNIVERSE getContainersOfDrugs:cargo_to_go]];
cargo_chance = 100; // chance of any given piece of cargo surviving decompression
cargo_flag = CARGO_FLAG_CANISTERS;
}
if (cargo_flag == CARGO_FLAG_FULL_PLENTIFUL || cargo_flag == CARGO_FLAG_FULL_SCARCE)
{
cargo_to_go = max_cargo / 10;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
[self setCargo:[UNIVERSE getContainersOfGoods:cargo_to_go scarce:(cargo_flag == CARGO_FLAG_FULL_SCARCE)]];
cargo_chance = 100;
}
while ([cargo count] > 0)
{
if (Ranrot() % 100 < cargo_chance) // 10% chance of any given piece of cargo surviving decompression
NS_DURING
//scripting
if (script != nil)
{
ShipEntity* container = [[cargo objectAtIndex:0] retain];
Vector rpos = xposition;
Vector rrand = randomPositionInBoundingBox(boundingBox);
rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
rpos.x += (ranrot_rand() % 7) - 3;
rpos.y += (ranrot_rand() % 7) - 3;
rpos.z += (ranrot_rand() % 7) - 3;
[container setPosition:rpos];
[container setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:container]; // STATUS_IN_FLIGHT, AI state GLOBAL
[container release];
if (n_cargo > 0)
n_cargo--; // count down extra cargo
[[PlayerEntity sharedPlayer] setScriptTarget:self];
[self doScriptEvent:@"shipDied"]; // FIXME: params missing
}
[cargo removeObjectAtIndex:0];
}
NSEnumerator *subEnum = nil;
ShipEntity *se = nil;
for (subEnum = [self shipSubEntityEnumerator]; (se = [subEnum nextObject]); )
{
[se setSuppressExplosion:suppressExplosion];
[se setPosition:[se absolutePositionForSubentity]];
[UNIVERSE addEntity:se];
[se becomeExplosion];
}
[self clearSubEntities];
if (!isPlayer) [UNIVERSE removeEntity:self];
// two parts to the explosion:
// 1. fast sparks
float how_many = factor;
while (how_many > 0.5f)
{
fragment = [[ParticleEntity alloc] initFragburstSize: collision_radius fromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
how_many -= 1.0f;
}
// 2. slow clouds
how_many = factor;
while (how_many > 0.5f)
{
fragment = [[ParticleEntity alloc] initBurst2Size: collision_radius fromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
how_many -= 1.0f;
}
// we need to throw out cargo at this point.
unsigned cargo_chance = 10;
if ([[name lowercaseString] rangeOfString:@"medical"].location != NSNotFound)
{
cargo_to_go = max_cargo * cargo_chance / 100;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
[self setCargo:[UNIVERSE getContainersOfDrugs:cargo_to_go]];
cargo_chance = 100; // chance of any given piece of cargo surviving decompression
cargo_flag = CARGO_FLAG_CANISTERS;
}
if (cargo_flag == CARGO_FLAG_FULL_PLENTIFUL || cargo_flag == CARGO_FLAG_FULL_SCARCE)
{
cargo_to_go = max_cargo / 10;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
[self setCargo:[UNIVERSE getContainersOfGoods:cargo_to_go scarce:(cargo_flag == CARGO_FLAG_FULL_SCARCE)]];
cargo_chance = 100;
}
while ([cargo count] > 0)
{
if (Ranrot() % 100 < cargo_chance) // 10% chance of any given piece of cargo surviving decompression
{
ShipEntity* container = [[cargo objectAtIndex:0] retain];
Vector rpos = xposition;
Vector rrand = randomPositionInBoundingBox(boundingBox);
rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
rpos.x += (ranrot_rand() % 7) - 3;
rpos.y += (ranrot_rand() % 7) - 3;
rpos.z += (ranrot_rand() % 7) - 3;
[container setPosition:rpos];
[container setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:container]; // STATUS_IN_FLIGHT, AI state GLOBAL
[container release];
if (n_cargo > 0)
n_cargo--; // count down extra cargo
}
[cargo removeObjectAtIndex:0];
}
NSEnumerator *subEnum = nil;
ShipEntity *se = nil;
for (subEnum = [self shipSubEntityEnumerator]; (se = [subEnum nextObject]); )
{
[se setSuppressExplosion:suppressExplosion];
[se setPosition:[se absolutePositionForSubentity]];
[UNIVERSE addEntity:se];
[se becomeExplosion];
}
[self clearSubEntities];
if (!isPlayer) [UNIVERSE removeEntity:self];
NS_HANDLER
if (!isPlayer) [UNIVERSE removeEntity:self];
NS_ENDHANDLER
}

View File

@ -5436,7 +5436,8 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
universal_time += delta_t;
update_stage = @"demo management";
if (inGUIMode && [player guiScreen] == GUI_SCREEN_INTRO2){
if (inGUIMode && [player guiScreen] == GUI_SCREEN_INTRO2)
{
if (universal_time >= demo_stage_time)
{
if (ent_count > 1)
@ -5517,12 +5518,20 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
}
update_stage = @"update:entity";
NSMutableSet *zombies = nil;
for (i = 0; i < ent_count; i++)
{
Entity *thing = my_entities[i];
#ifndef NDEBUG
update_stage = [NSString stringWithFormat:@"update:entity[%@]", [thing shortDescription]];
#endif
if (EXPECT_NOT([thing status] == STATUS_DEAD && ![entitiesDeadThisUpdate containsObject:thing]))
{
if (zombies == nil) zombies = [NSMutableSet set];
[zombies addObject:thing];
continue;
}
[thing update:delta_t];
@ -5558,6 +5567,18 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
}
}
if (zombies != nil)
{
update_stage = @"shootin' zombies";
NSEnumerator *zombieEnum = nil;
Entity *zombie = nil;
for (zombieEnum = [zombies objectEnumerator]; (zombie = [zombieEnum nextObject]); )
{
OOLogERR(@"universe.zombie", @"Found dead entity %@ in active entity list, removing. This is an internal error, please report it.", zombie);
[self removeEntity:zombie];
}
}
// Maintain x/y/z order lists
update_stage = @"updating linked lists";
for (i = 0; i < ent_count; i++)