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

@ -208,8 +208,8 @@
"thargonCheckMother", "thargonCheckMother",
"addPrimaryAggressorAsDefenseTarget", "addPrimaryAggressorAsDefenseTarget",
"addFoundTargetAsDefenseTarget", "addFoundTargetAsDefenseTarget",
"findNewDefenseTarget", "findNewDefenseTarget",
"clearDefenseTargets", "clearDefenseTargets",
"storeTarget", "storeTarget",
"recallStoredTarget", "recallStoredTarget",
// StationEntity.m/stubs in ShipEntityAI.m // StationEntity.m/stubs in ShipEntityAI.m
@ -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;
- (BOOL) addDefenseTarget:(Entity*)target; - (NSEnumerator *) defenseTargetEnumerator;
- (BOOL) isDefenseTarget:(Entity*)target; - (BOOL) addDefenseTarget:(Entity *)target;
- (void) removeDefenseTarget:(unsigned)index; - (BOOL) isDefenseTarget:(Entity *)target;
- (void) removeDefenseTargetByID:(Entity*)target; - (void) removeDefenseTarget:(Entity *)target;
- (void) clearDefenseTargets; - (void) removeAllDefenseTargets;
- (GLfloat) weaponRange; - (GLfloat) weaponRange;
@ -741,13 +742,13 @@ typedef enum
- (void) setWeaponEnergy:(float)value; - (void) setWeaponEnergy:(float)value;
- (GLfloat) scannerRange; - (GLfloat) scannerRange;
- (void) setScannerRange: (GLfloat) value; - (void) setScannerRange:(GLfloat)value;
- (Vector) reference; - (Vector) reference;
- (void) setReference:(Vector) v; - (void) setReference:(Vector)v;
- (BOOL) reportAIMessages; - (BOOL) reportAIMessages;
- (void) setReportAIMessages:(BOOL) yn; - (void) setReportAIMessages:(BOOL)yn;
- (void) transitionToAegisNone; - (void) transitionToAegisNone;
- (OOPlanetEntity *) findNearestPlanet; - (OOPlanetEntity *) findNearestPlanet;
@ -757,18 +758,18 @@ typedef enum
- (BOOL) withinStationAegis; - (BOOL) withinStationAegis;
- (NSArray*) crew; - (NSArray*) crew;
- (void) setCrew: (NSArray*) crewArray; - (void) setCrew:(NSArray *)crewArray;
// Fuel and capacity in tenths of light-years. // Fuel and capacity in tenths of light-years.
- (OOFuelQuantity) fuel; - (OOFuelQuantity) fuel;
- (void) setFuel:(OOFuelQuantity) amount; - (void) setFuel:(OOFuelQuantity)amount;
- (OOFuelQuantity) fuelCapacity; - (OOFuelQuantity) fuelCapacity;
- (GLfloat) fuelChargeRate; - (GLfloat) fuelChargeRate;
- (void) setRoll:(double) amount; - (void) setRoll:(double)amount;
- (void) setPitch:(double) amount; - (void) setPitch:(double)amount;
- (void) setThrust:(double) amount; - (void) setThrust:(double)amount;
- (void) applySticks:(double)delta_t; - (void) applySticks:(double)delta_t;
@ -778,14 +779,14 @@ typedef enum
Sets the bounty on this ship to amount. Sets the bounty on this ship to amount.
Does not check to see if the ship is allowed to have a bounty, for example if it is police. Does not check to see if the ship is allowed to have a bounty, for example if it is police.
*/ */
- (void) setBounty:(OOCreditsQuantity) amount; - (void) setBounty:(OOCreditsQuantity)amount;
- (void) setBounty:(OOCreditsQuantity) amount withReason:(OOLegalStatusReason)reason; - (void) setBounty:(OOCreditsQuantity)amount withReason:(OOLegalStatusReason)reason;
- (void) setBounty:(OOCreditsQuantity) amount withReasonAsString:(NSString *)reason; - (void) setBounty:(OOCreditsQuantity)amount withReasonAsString:(NSString *)reason;
- (OOCreditsQuantity) bounty; - (OOCreditsQuantity) bounty;
- (int) legalStatus; - (int) legalStatus;
- (void) setUpCargoType:(NSString *) cargoString; - (void) setUpCargoType:(NSString *)cargoString;
- (void) setCommodity:(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount; - (void) setCommodity:(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount;
- (void) setCommodityForPod:(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount; - (void) setCommodityForPod:(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount;
- (OOCommodityType) commodityType; - (OOCommodityType) commodityType;
@ -796,35 +797,35 @@ typedef enum
- (OOCargoQuantity) cargoQuantityOnBoard; - (OOCargoQuantity) cargoQuantityOnBoard;
- (OOCargoType) cargoType; - (OOCargoType) cargoType;
- (NSMutableArray *) cargo; - (NSMutableArray *) cargo;
- (void) setCargo:(NSArray *) some_cargo; - (void) setCargo:(NSArray *)some_cargo;
- (BOOL) showScoopMessage; - (BOOL) showScoopMessage;
- (NSArray *) passengerListForScripting; - (NSArray *) passengerListForScripting;
- (NSArray *) contractListForScripting; - (NSArray *) contractListForScripting;
- (NSArray *) equipmentListForScripting; - (NSArray *) equipmentListForScripting;
- (OOEquipmentType *) weaponTypeForFacing:(int) facing; - (OOEquipmentType *) weaponTypeForFacing:(int)facing;
- (NSArray *) missilesList; - (NSArray *) missilesList;
- (OOCargoFlag) cargoFlag; - (OOCargoFlag) cargoFlag;
- (void) setCargoFlag:(OOCargoFlag) flag; - (void) setCargoFlag:(OOCargoFlag)flag;
- (void) setSpeed:(double) amount; - (void) setSpeed:(double)amount;
- (double) desiredSpeed; - (double) desiredSpeed;
- (void) setDesiredSpeed:(double) amount; - (void) setDesiredSpeed:(double)amount;
- (double) cruiseSpeed; - (double) cruiseSpeed;
- (Vector) thrustVector; - (Vector) thrustVector;
- (void) setTotalVelocity:(Vector)vel; // Set velocity to vel - thrustVector, effectively setting the instanteneous velocity to vel. - (void) setTotalVelocity:(Vector)vel; // Set velocity to vel - thrustVector, effectively setting the instanteneous velocity to vel.
- (void) increase_flight_speed:(double) delta; - (void) increase_flight_speed:(double)delta;
- (void) decrease_flight_speed:(double) delta; - (void) decrease_flight_speed:(double)delta;
- (void) increase_flight_roll:(double) delta; - (void) increase_flight_roll:(double)delta;
- (void) decrease_flight_roll:(double) delta; - (void) decrease_flight_roll:(double)delta;
- (void) increase_flight_pitch:(double) delta; - (void) increase_flight_pitch:(double)delta;
- (void) decrease_flight_pitch:(double) delta; - (void) decrease_flight_pitch:(double)delta;
- (void) increase_flight_yaw:(double) delta; - (void) increase_flight_yaw:(double)delta;
- (void) decrease_flight_yaw:(double) delta; - (void) decrease_flight_yaw:(double)delta;
- (GLfloat) flightRoll; - (GLfloat) flightRoll;
- (GLfloat) flightPitch; - (GLfloat) flightPitch;

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"
@ -622,10 +623,7 @@ static ShipEntity *doOctreesCollide(ShipEntity *prime, ShipEntity *other);
if ((isUnpiloted = [shipDict oo_fuzzyBooleanForKey:@"unpiloted"])) [self setCrew:nil]; if ((isUnpiloted = [shipDict oo_fuzzyBooleanForKey:@"unpiloted"])) [self setCrew:nil];
[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];
@ -5079,26 +5076,25 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
} }
return; return;
} }
// can't fire on primary target; track secondary targets instead
unsigned i;
for (i = 0; i < [turret_owner numDefenseTargets]; i++) // can't fire on primary target; track secondary targets instead
NSEnumerator *targetEnum = [turret_owner defenseTargetEnumerator];
Entity *target = nil;
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)
@ -5107,17 +5103,17 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
} }
return; return;
} }
// else that target is out of range, try the next priority defense target // else that target is out of range, try the next priority defense target
} }
else if (range > scannerRange) else if (range > scannerRange)
{ {
[turret_owner removeDefenseTarget:i--]; [turret_owner removeDefenseTarget:target];
} }
} }
} }
// turrets now don't return to neutral facing if no suitable target // turrets now don't return to neutral facing if no suitable target
// better for shooting at targets that are on edge of fire arc // better for shooting at targets that are on edge of fire arc
} }
@ -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;