Use OOWeakSet for ship defense targets.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@5151 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2012-07-30 23:13:55 +00:00
parent c24d971705
commit a9c0e85649
7 changed files with 113 additions and 129 deletions

View File

@ -241,7 +241,8 @@
"setTargetToNearestFriendlyStation", "setTargetToNearestFriendlyStation",
"setTargetToSystemStation", "setTargetToSystemStation",
"setUpEscorts", "setUpEscorts",
"fireMissile" "fireMissile",
"removeAllDefenseTargets" // Don't use, use clearDefenseTargets instead
); );
ai_and_action_methods = ai_and_action_methods =
@ -456,5 +457,6 @@
"scanForRandomMerchantmen" = "scanForRandomMerchantman"; "scanForRandomMerchantmen" = "scanForRandomMerchantman";
"setUpEscorts" = "doNothing"; "setUpEscorts" = "doNothing";
"becomeExplosion" = "explodeSelf"; "becomeExplosion" = "explodeSelf";
"clearDefenseTargets" = "removeAllDefenseTargets";
}; };
} }

View File

@ -30,7 +30,7 @@
#import "OOJSPropID.h" #import "OOJSPropID.h"
@class OOColor, StationEntity, WormholeEntity, AI, Octree, OOMesh, OOScript, @class OOColor, StationEntity, WormholeEntity, AI, Octree, OOMesh, OOScript,
OOJSScript, OORoleSet, OOShipGroup, OOEquipmentType; OOJSScript, OORoleSet, OOShipGroup, OOEquipmentType, OOWeakSet;
#ifdef OO_BRAIN_AI #ifdef OO_BRAIN_AI
@class OOBrain; @class OOBrain;
@ -323,7 +323,6 @@ typedef enum
Vector jink; // x and y set factors for offsetting a pursuing ship's position Vector jink; // x and y set factors for offsetting a pursuing ship's position
Vector coordinates; // for flying to/from a set point Vector coordinates; // for flying to/from a set point
Vector reference; // a direction vector of magnitude 1 (* turrets *) Vector reference; // a direction vector of magnitude 1 (* turrets *)
NSMutableArray *defenseTargets; // defense targets
OOUInteger _subIdx; // serialisation index - used only if this ship is a subentity OOUInteger _subIdx; // serialisation index - used only if this ship is a subentity
OOUInteger _maxShipSubIdx; // serialisation index - the number of ship subentities inside the shipdata OOUInteger _maxShipSubIdx; // serialisation index - the number of ship subentities inside the shipdata
@ -443,6 +442,8 @@ typedef enum
Vector _escortPositions[MAX_ESCORTS]; Vector _escortPositions[MAX_ESCORTS];
BOOL _escortPositionsValid; BOOL _escortPositionsValid;
OOWeakSet *_defenseTargets; // defense targets
GLfloat _profileRadius; GLfloat _profileRadius;
OOWeakReference *_shipHitByLaser; // entity hit by the last laser shot OOWeakReference *_shipHitByLaser; // entity hit by the last laser shot
@ -724,13 +725,13 @@ typedef enum
- (BOOL) isHostileTo:(Entity *)entity; - (BOOL) isHostileTo:(Entity *)entity;
// defense target handling // defense target handling
- (unsigned) numDefenseTargets; - (OOUInteger) defenseTargetCount;
- (Entity*) getDefenseTarget:(int)index; - (NSArray *) allDefenseTargets;
- (NSEnumerator *) defenseTargetEnumerator;
- (BOOL) addDefenseTarget:(Entity *)target; - (BOOL) addDefenseTarget:(Entity *)target;
- (BOOL) isDefenseTarget:(Entity *)target; - (BOOL) isDefenseTarget:(Entity *)target;
- (void) removeDefenseTarget:(unsigned)index; - (void) removeDefenseTarget:(Entity *)target;
- (void) removeDefenseTargetByID:(Entity*)target; - (void) removeAllDefenseTargets;
- (void) clearDefenseTargets;
- (GLfloat) weaponRange; - (GLfloat) weaponRange;

View File

@ -43,6 +43,7 @@ MA 02110-1301, USA.
#import "OORoleSet.h" #import "OORoleSet.h"
#import "OOShipGroup.h" #import "OOShipGroup.h"
#import "OOExcludeObjectEnumerator.h" #import "OOExcludeObjectEnumerator.h"
#import "OOWeakSet.h"
#import "OOCharacter.h" #import "OOCharacter.h"
#import "AI.h" #import "AI.h"
@ -623,9 +624,6 @@ static ShipEntity *doOctreesCollide(ShipEntity *prime, ShipEntity *other);
[self setShipScript:[shipDict oo_stringForKey:@"script"]]; [self setShipScript:[shipDict oo_stringForKey:@"script"]];
// retained array of defense targets
defenseTargets = [[NSMutableArray alloc] initWithCapacity:MAX_TARGETS];
return YES; return YES;
OOJS_PROFILE_EXIT OOJS_PROFILE_EXIT
@ -947,8 +945,7 @@ static ShipEntity *doOctreesCollide(ShipEntity *prime, ShipEntity *other);
DESTROY(crew); DESTROY(crew);
DESTROY(lastRadioMessage); DESTROY(lastRadioMessage);
DESTROY(octree); DESTROY(octree);
[defenseTargets removeAllObjects]; DESTROY(_defenseTargets);
DESTROY(defenseTargets);
[self setSubEntityTakingDamage:nil]; [self setSubEntityTakingDamage:nil];
[self removeAllEquipment]; [self removeAllEquipment];
@ -5081,24 +5078,23 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
} }
// can't fire on primary target; track secondary targets instead // can't fire on primary target; track secondary targets instead
unsigned i; NSEnumerator *targetEnum = [turret_owner defenseTargetEnumerator];
Entity *target = nil;
for (i = 0; i < [turret_owner numDefenseTargets]; i++) while ((target = [targetEnum nextObject]))
{ {
Entity *my_target = [turret_owner getDefenseTarget:i]; if ([target scanClass] == CLASS_NO_DRAW || [(ShipEntity *)target isCloaked] || [target energy] <= 0.0)
if (my_target == nil || [my_target scanClass] == CLASS_NO_DRAW || ![my_target isShip] || [(ShipEntity *)my_target isCloaked] || [my_target energy] <= 0.0)
{ {
[turret_owner removeDefenseTarget:i--]; [turret_owner removeDefenseTarget:target];
} }
else else
{ {
double range = [turret_owner rangeToSecondaryTarget:my_target]; double range = [turret_owner rangeToSecondaryTarget:target];
if (range < weaponRange) if (range < weaponRange)
{ {
aim = [self ballTrackLeadingTarget:delta_t atTarget:my_target]; aim = [self ballTrackLeadingTarget:delta_t atTarget:target];
if (aim > -1.0) if (aim > -1.0)
{ // tracking... { // tracking...
Vector p = vector_subtract([my_target position], [turret_owner position]); Vector p = vector_subtract([target position], [turret_owner position]);
double cr = [turret_owner collisionRadius]; double cr = [turret_owner collisionRadius];
if (aim > .95) if (aim > .95)
@ -5111,7 +5107,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
} }
else if (range > scannerRange) else if (range > scannerRange)
{ {
[turret_owner removeDefenseTarget:i--]; [turret_owner removeDefenseTarget:target];
} }
} }
} }
@ -8316,7 +8312,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
ShipEntity* ship = [self primaryTarget]; ShipEntity* ship = [self primaryTarget];
if ([self isDefenseTarget:ship]) if ([self isDefenseTarget:ship])
{ {
[self removeDefenseTargetByID:ship]; [self removeDefenseTarget:ship];
} }
target = (ship && ship->isShip) ? (id)ship : nil; target = (ship && ship->isShip) ? (id)ship : nil;
if ([self primaryAggressor] == ship) if ([self primaryAggressor] == ship)
@ -8350,7 +8346,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
} }
if ([self isDefenseTarget:target]) if ([self isDefenseTarget:target])
{ {
[self removeDefenseTargetByID:target]; [self removeDefenseTarget:target];
[shipAI message:@"DEFENSE_TARGET_DESTROYED"]; [shipAI message:@"DEFENSE_TARGET_DESTROYED"];
} }
} }
@ -9215,21 +9211,27 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
} }
- (unsigned) numDefenseTargets - (OOUInteger) defenseTargetCount
{ {
return [defenseTargets count]; return [_defenseTargets count];
} }
- (Entity*) getDefenseTarget:(int)index - (NSArray *) allDefenseTargets
{ {
return [[defenseTargets objectAtIndex:index] weakRefUnderlyingObject]; return [_defenseTargets allObjects];
}
- (NSEnumerator *) defenseTargetEnumerator
{
return [_defenseTargets objectEnumerator];
} }
- (BOOL) addDefenseTarget:(Entity *)target - (BOOL) addDefenseTarget:(Entity *)target
{ {
if ([defenseTargets count] >= MAX_TARGETS) if ([self defenseTargetCount] >= MAX_TARGETS)
{ {
return NO; return NO;
} }
@ -9237,62 +9239,33 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
{ {
return NO; return NO;
} }
[defenseTargets addObject:[[target weakRetain] autorelease]]; if (_defenseTargets == nil)
{
// Allocate lazily for the benefit of the ships that never get in fights.
_defenseTargets = [[OOWeakSet alloc] init];
}
[_defenseTargets addObject:target];
return YES; return YES;
} }
- (BOOL) isDefenseTarget:(Entity *)target - (BOOL) isDefenseTarget:(Entity *)target
{ {
if (target == nil) return [_defenseTargets containsObject:target];
{
return NO;
}
for (unsigned i=0; i<[defenseTargets count]; i++)
{
if ([[defenseTargets objectAtIndex:i] weakRefUnderlyingObject] == target)
{
return YES;
}
}
return NO;
} }
// exposed to AI // exposed to AI (as alias of clearDefenseTargets)
- (void) clearDefenseTargets - (void) removeAllDefenseTargets
{ {
[defenseTargets removeAllObjects]; [_defenseTargets removeAllObjects];
} }
- (void) removeDefenseTarget:(unsigned)index - (void) removeDefenseTarget:(Entity *)target
{ {
if (index < [defenseTargets count]) [_defenseTargets removeObject:target];
{
if ([defenseTargets count] == 1)
{
[shipAI reactToMessage:@"DEFENSE_TARGET_LOST" context:@"flight updates"]; // last defense target lost
}
else
{
[shipAI message:@"DEFENSE_TARGET_LOST"]; // no major urgency, we have more
}
[defenseTargets removeObjectAtIndex:index];
}
}
- (void) removeDefenseTargetByID:(Entity *)target
{
for (unsigned i=0; i<[defenseTargets count]; i++)
{
if ([[defenseTargets objectAtIndex:i] weakRefUnderlyingObject] == target)
{
[self removeDefenseTarget:i];
return;
}
}
} }
@ -9729,24 +9702,24 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
- (BOOL) fireDirectLaserDefensiveShot - (BOOL) fireDirectLaserDefensiveShot
{ {
unsigned i; NSEnumerator *targetEnum = [self defenseTargetEnumerator];
for (i = 0; i < [defenseTargets count]; i++) Entity *target = nil;
while ((target = [targetEnum nextObject]))
{ {
Entity *my_target = [self getDefenseTarget:i]; if ([target scanClass] == CLASS_NO_DRAW || [(ShipEntity *)target isCloaked] || [target energy] <= 0.0)
if (my_target == nil || [my_target scanClass] == CLASS_NO_DRAW || ![my_target isShip] || [(ShipEntity *)my_target isCloaked] || [my_target energy] <= 0.0)
{ {
[self removeDefenseTarget:i--]; [self removeDefenseTarget:target];
} }
else else
{ {
double range = [self rangeToSecondaryTarget:my_target]; double range = [self rangeToSecondaryTarget:target];
if (range < weaponRange) if (range < weaponRange)
{ {
return [self fireDirectLaserShotAt:my_target]; return [self fireDirectLaserShotAt:target];
} }
else if (range > scannerRange) else if (range > scannerRange)
{ {
[self removeDefenseTarget:i--]; [self removeDefenseTarget:target];
} }
} }
} }

View File

@ -1507,7 +1507,7 @@
} }
if ([other isDefenseTarget:self]) if ([other isDefenseTarget:self])
{ {
[other removeDefenseTargetByID:self]; [other removeDefenseTarget:self];
} }
} }
// now we're just a bunch of alien artefacts! // now we're just a bunch of alien artefacts!

View File

@ -49,6 +49,8 @@ This code is hereby placed in the public domain.
- (void) makeObjectsPerformSelector:(SEL)selector; - (void) makeObjectsPerformSelector:(SEL)selector;
- (void) makeObjectsPerformSelector:(SEL)selector withObject:(id)argument; - (void) makeObjectsPerformSelector:(SEL)selector withObject:(id)argument;
- (NSArray *) allObjects;
- (void) removeAllObjects; - (void) removeAllObjects;
@end @end

View File

@ -212,6 +212,24 @@ This code is hereby placed in the public domain.
} }
- (NSArray *) allObjects
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[_objects count]];
OOWeakReference *weakRef = nil;
foreach (weakRef, _objects)
{
id object = [weakRef weakRefUnderlyingObject];
if (object != nil) [result addObject:object];
}
#ifdef NDEBUG
return result;
#else
return [NSArray arrayWithArray:result];
#endif
}
- (void) removeAllObjects - (void) removeAllObjects
{ {
[_objects removeAllObjects]; [_objects removeAllObjects];

View File

@ -465,21 +465,9 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, j
break; break;
case kShip_defenseTargets: case kShip_defenseTargets:
{ result = [entity allDefenseTargets];
unsigned ndts = [entity numDefenseTargets];
NSMutableArray* targets = [NSMutableArray arrayWithCapacity:ndts];
for (unsigned i=0;i<ndts;i++)
{
Entity *dtarget = [entity getDefenseTarget:i];
if (dtarget != nil)
{
[targets addObject:dtarget];
}
}
result = [NSArray arrayWithArray:targets];
if ([result count] == 0) result = nil;
break; break;
}
case kShip_escorts: case kShip_escorts:
result = [[entity escortGroup] memberArrayExcludingLeader]; result = [[entity escortGroup] memberArrayExcludingLeader];
if ([result count] == 0) result = nil; if ([result count] == 0) result = nil;
@ -2363,7 +2351,7 @@ static JSBool ShipClearDefenseTargets(JSContext *context, uintN argc, jsval *vp)
ShipEntity *thisEnt = nil; ShipEntity *thisEnt = nil;
GET_THIS_SHIP(thisEnt); GET_THIS_SHIP(thisEnt);
[thisEnt clearDefenseTargets]; [thisEnt removeAllDefenseTargets];
OOJS_RETURN_VOID; OOJS_RETURN_VOID;