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",
"setTargetToSystemStation",
"setUpEscorts",
"fireMissile"
"fireMissile",
"removeAllDefenseTargets" // Don't use, use clearDefenseTargets instead
);
ai_and_action_methods =
@ -456,5 +457,6 @@
"scanForRandomMerchantmen" = "scanForRandomMerchantman";
"setUpEscorts" = "doNothing";
"becomeExplosion" = "explodeSelf";
"clearDefenseTargets" = "removeAllDefenseTargets";
};
}

View File

@ -30,7 +30,7 @@
#import "OOJSPropID.h"
@class OOColor, StationEntity, WormholeEntity, AI, Octree, OOMesh, OOScript,
OOJSScript, OORoleSet, OOShipGroup, OOEquipmentType;
OOJSScript, OORoleSet, OOShipGroup, OOEquipmentType, OOWeakSet;
#ifdef OO_BRAIN_AI
@class OOBrain;
@ -323,7 +323,6 @@ typedef enum
Vector jink; // x and y set factors for offsetting a pursuing ship's position
Vector coordinates; // for flying to/from a set point
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 _maxShipSubIdx; // serialisation index - the number of ship subentities inside the shipdata
@ -443,6 +442,8 @@ typedef enum
Vector _escortPositions[MAX_ESCORTS];
BOOL _escortPositionsValid;
OOWeakSet *_defenseTargets; // defense targets
GLfloat _profileRadius;
OOWeakReference *_shipHitByLaser; // entity hit by the last laser shot
@ -724,13 +725,13 @@ typedef enum
- (BOOL) isHostileTo:(Entity *)entity;
// defense target handling
- (unsigned) numDefenseTargets;
- (Entity*) getDefenseTarget:(int)index;
- (BOOL) addDefenseTarget:(Entity*)target;
- (BOOL) isDefenseTarget:(Entity*)target;
- (void) removeDefenseTarget:(unsigned)index;
- (void) removeDefenseTargetByID:(Entity*)target;
- (void) clearDefenseTargets;
- (OOUInteger) defenseTargetCount;
- (NSArray *) allDefenseTargets;
- (NSEnumerator *) defenseTargetEnumerator;
- (BOOL) addDefenseTarget:(Entity *)target;
- (BOOL) isDefenseTarget:(Entity *)target;
- (void) removeDefenseTarget:(Entity *)target;
- (void) removeAllDefenseTargets;
- (GLfloat) weaponRange;
@ -741,13 +742,13 @@ typedef enum
- (void) setWeaponEnergy:(float)value;
- (GLfloat) scannerRange;
- (void) setScannerRange: (GLfloat) value;
- (void) setScannerRange:(GLfloat)value;
- (Vector) reference;
- (void) setReference:(Vector) v;
- (void) setReference:(Vector)v;
- (BOOL) reportAIMessages;
- (void) setReportAIMessages:(BOOL) yn;
- (void) setReportAIMessages:(BOOL)yn;
- (void) transitionToAegisNone;
- (OOPlanetEntity *) findNearestPlanet;
@ -757,18 +758,18 @@ typedef enum
- (BOOL) withinStationAegis;
- (NSArray*) crew;
- (void) setCrew: (NSArray*) crewArray;
- (void) setCrew:(NSArray *)crewArray;
// Fuel and capacity in tenths of light-years.
- (OOFuelQuantity) fuel;
- (void) setFuel:(OOFuelQuantity) amount;
- (void) setFuel:(OOFuelQuantity)amount;
- (OOFuelQuantity) fuelCapacity;
- (GLfloat) fuelChargeRate;
- (void) setRoll:(double) amount;
- (void) setPitch:(double) amount;
- (void) setThrust:(double) amount;
- (void) setRoll:(double)amount;
- (void) setPitch:(double)amount;
- (void) setThrust:(double)amount;
- (void) applySticks:(double)delta_t;
@ -778,14 +779,14 @@ typedef enum
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.
*/
- (void) setBounty:(OOCreditsQuantity) amount;
- (void) setBounty:(OOCreditsQuantity) amount withReason:(OOLegalStatusReason)reason;
- (void) setBounty:(OOCreditsQuantity) amount withReasonAsString:(NSString *)reason;
- (void) setBounty:(OOCreditsQuantity)amount;
- (void) setBounty:(OOCreditsQuantity)amount withReason:(OOLegalStatusReason)reason;
- (void) setBounty:(OOCreditsQuantity)amount withReasonAsString:(NSString *)reason;
- (OOCreditsQuantity) bounty;
- (int) legalStatus;
- (void) setUpCargoType:(NSString *) cargoString;
- (void) setUpCargoType:(NSString *)cargoString;
- (void) setCommodity:(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount;
- (void) setCommodityForPod:(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount;
- (OOCommodityType) commodityType;
@ -796,35 +797,35 @@ typedef enum
- (OOCargoQuantity) cargoQuantityOnBoard;
- (OOCargoType) cargoType;
- (NSMutableArray *) cargo;
- (void) setCargo:(NSArray *) some_cargo;
- (void) setCargo:(NSArray *)some_cargo;
- (BOOL) showScoopMessage;
- (NSArray *) passengerListForScripting;
- (NSArray *) contractListForScripting;
- (NSArray *) equipmentListForScripting;
- (OOEquipmentType *) weaponTypeForFacing:(int) facing;
- (OOEquipmentType *) weaponTypeForFacing:(int)facing;
- (NSArray *) missilesList;
- (OOCargoFlag) cargoFlag;
- (void) setCargoFlag:(OOCargoFlag) flag;
- (void) setCargoFlag:(OOCargoFlag)flag;
- (void) setSpeed:(double) amount;
- (void) setSpeed:(double)amount;
- (double) desiredSpeed;
- (void) setDesiredSpeed:(double) amount;
- (void) setDesiredSpeed:(double)amount;
- (double) cruiseSpeed;
- (Vector) thrustVector;
- (void) setTotalVelocity:(Vector)vel; // Set velocity to vel - thrustVector, effectively setting the instanteneous velocity to vel.
- (void) increase_flight_speed:(double) delta;
- (void) decrease_flight_speed:(double) delta;
- (void) increase_flight_roll:(double) delta;
- (void) decrease_flight_roll:(double) delta;
- (void) increase_flight_pitch:(double) delta;
- (void) decrease_flight_pitch:(double) delta;
- (void) increase_flight_yaw:(double) delta;
- (void) decrease_flight_yaw:(double) delta;
- (void) increase_flight_speed:(double)delta;
- (void) decrease_flight_speed:(double)delta;
- (void) increase_flight_roll:(double)delta;
- (void) decrease_flight_roll:(double)delta;
- (void) increase_flight_pitch:(double)delta;
- (void) decrease_flight_pitch:(double)delta;
- (void) increase_flight_yaw:(double)delta;
- (void) decrease_flight_yaw:(double)delta;
- (GLfloat) flightRoll;
- (GLfloat) flightPitch;

View File

@ -43,6 +43,7 @@ MA 02110-1301, USA.
#import "OORoleSet.h"
#import "OOShipGroup.h"
#import "OOExcludeObjectEnumerator.h"
#import "OOWeakSet.h"
#import "OOCharacter.h"
#import "AI.h"
@ -623,9 +624,6 @@ static ShipEntity *doOctreesCollide(ShipEntity *prime, ShipEntity *other);
[self setShipScript:[shipDict oo_stringForKey:@"script"]];
// retained array of defense targets
defenseTargets = [[NSMutableArray alloc] initWithCapacity:MAX_TARGETS];
return YES;
OOJS_PROFILE_EXIT
@ -947,8 +945,7 @@ static ShipEntity *doOctreesCollide(ShipEntity *prime, ShipEntity *other);
DESTROY(crew);
DESTROY(lastRadioMessage);
DESTROY(octree);
[defenseTargets removeAllObjects];
DESTROY(defenseTargets);
DESTROY(_defenseTargets);
[self setSubEntityTakingDamage:nil];
[self removeAllEquipment];
@ -5080,25 +5077,24 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
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 (my_target == nil || [my_target scanClass] == CLASS_NO_DRAW || ![my_target isShip] || [(ShipEntity *)my_target isCloaked] || [my_target energy] <= 0.0)
if ([target scanClass] == CLASS_NO_DRAW || [(ShipEntity *)target isCloaked] || [target energy] <= 0.0)
{
[turret_owner removeDefenseTarget:i--];
[turret_owner removeDefenseTarget:target];
}
else
{
double range = [turret_owner rangeToSecondaryTarget:my_target];
double range = [turret_owner rangeToSecondaryTarget:target];
if (range < weaponRange)
{
aim = [self ballTrackLeadingTarget:delta_t atTarget:my_target];
aim = [self ballTrackLeadingTarget:delta_t atTarget:target];
if (aim > -1.0)
{ // 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];
if (aim > .95)
@ -5107,11 +5103,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
}
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)
{
[turret_owner removeDefenseTarget:i--];
[turret_owner removeDefenseTarget:target];
}
}
}
@ -8316,7 +8312,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
ShipEntity* ship = [self primaryTarget];
if ([self isDefenseTarget:ship])
{
[self removeDefenseTargetByID:ship];
[self removeDefenseTarget:ship];
}
target = (ship && ship->isShip) ? (id)ship : nil;
if ([self primaryAggressor] == ship)
@ -8350,7 +8346,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
}
if ([self isDefenseTarget:target])
{
[self removeDefenseTargetByID:target];
[self removeDefenseTarget:target];
[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
{
if ([defenseTargets count] >= MAX_TARGETS)
if ([self defenseTargetCount] >= MAX_TARGETS)
{
return NO;
}
@ -9237,62 +9239,33 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
{
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;
}
- (BOOL) isDefenseTarget:(Entity *)target
{
if (target == nil)
{
return NO;
}
for (unsigned i=0; i<[defenseTargets count]; i++)
{
if ([[defenseTargets objectAtIndex:i] weakRefUnderlyingObject] == target)
{
return YES;
}
}
return NO;
return [_defenseTargets containsObject:target];
}
// exposed to AI
- (void) clearDefenseTargets
// exposed to AI (as alias of clearDefenseTargets)
- (void) removeAllDefenseTargets
{
[defenseTargets removeAllObjects];
[_defenseTargets removeAllObjects];
}
- (void) removeDefenseTarget:(unsigned)index
- (void) removeDefenseTarget:(Entity *)target
{
if (index < [defenseTargets count])
{
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;
}
}
[_defenseTargets removeObject:target];
}
@ -9729,24 +9702,24 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
- (BOOL) fireDirectLaserDefensiveShot
{
unsigned i;
for (i = 0; i < [defenseTargets count]; i++)
NSEnumerator *targetEnum = [self defenseTargetEnumerator];
Entity *target = nil;
while ((target = [targetEnum nextObject]))
{
Entity *my_target = [self getDefenseTarget:i];
if (my_target == nil || [my_target scanClass] == CLASS_NO_DRAW || ![my_target isShip] || [(ShipEntity *)my_target isCloaked] || [my_target energy] <= 0.0)
if ([target scanClass] == CLASS_NO_DRAW || [(ShipEntity *)target isCloaked] || [target energy] <= 0.0)
{
[self removeDefenseTarget:i--];
[self removeDefenseTarget:target];
}
else
{
double range = [self rangeToSecondaryTarget:my_target];
double range = [self rangeToSecondaryTarget:target];
if (range < weaponRange)
{
return [self fireDirectLaserShotAt:my_target];
return [self fireDirectLaserShotAt:target];
}
else if (range > scannerRange)
{
[self removeDefenseTarget:i--];
[self removeDefenseTarget:target];
}
}
}

View File

@ -1507,7 +1507,7 @@
}
if ([other isDefenseTarget:self])
{
[other removeDefenseTargetByID:self];
[other removeDefenseTarget:self];
}
}
// 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 withObject:(id)argument;
- (NSArray *) allObjects;
- (void) removeAllObjects;
@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
{
[_objects removeAllObjects];

View File

@ -465,21 +465,9 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, j
break;
case kShip_defenseTargets:
{
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;
result = [entity allDefenseTargets];
break;
}
case kShip_escorts:
result = [[entity escortGroup] memberArrayExcludingLeader];
if ([result count] == 0) result = nil;
@ -2363,7 +2351,7 @@ static JSBool ShipClearDefenseTargets(JSContext *context, uintN argc, jsval *vp)
ShipEntity *thisEnt = nil;
GET_THIS_SHIP(thisEnt);
[thisEnt clearDefenseTargets];
[thisEnt removeAllDefenseTargets];
OOJS_RETURN_VOID;