oolite/src/Core/Entities/Entity.m

1145 lines
22 KiB
Objective-C

/*
Entity.m
Oolite
Copyright (C) 2004-2013 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "Entity.h"
#import "EntityOOJavaScriptExtensions.h"
#import "PlayerEntity.h"
#import "OOPlanetEntity.h"
#import "OOMaths.h"
#import "Universe.h"
#import "GameController.h"
#import "ResourceManager.h"
#import "OOConstToString.h"
#import "CollisionRegion.h"
#import "NSScannerOOExtensions.h"
#import "OODebugFlags.h"
#import "NSObjectOOExtensions.h"
#ifndef NDEBUG
uint32_t gLiveEntityCount = 0;
size_t gTotalEntityMemory = 0;
#endif
#ifndef NDEBUG
static NSString * const kOOLogEntityAddToList = @"entity.linkedList.add";
static NSString * const kOOLogEntityAddToListError = @"entity.linkedList.add.error";
static NSString * const kOOLogEntityRemoveFromList = @"entity.linkedList.remove";
static NSString * const kOOLogEntityRemoveFromListError = @"entity.linkedList.remove.error";
static NSString * const kOOLogEntityUpdateError = @"entity.linkedList.update.error";
#endif
static NSString * const kOOLogEntityVerificationError = @"entity.linkedList.verify.error";
@interface Entity (OOPrivate)
- (BOOL) checkLinkedLists;
@end
@implementation Entity
- (id) init
{
self = [super init];
if (EXPECT_NOT(self == nil)) return nil;
_sessionID = [UNIVERSE sessionID];
orientation = kIdentityQuaternion;
rotMatrix = kIdentityMatrix;
position = kZeroHPVector;
no_draw_distance = 100000.0; // 10 km
collidingEntities = [[NSMutableArray alloc] init];
scanClass = CLASS_NOT_SET;
[self setStatus:STATUS_COCKPIT_DISPLAY];
spawnTime = [UNIVERSE getTime];
isSunlit = YES;
atmosphereFogging = [[OOColor colorWithRed: 0.0 green: 0.0 blue: 0.0 alpha: 0.0] retain];
#ifndef NDEBUG
gLiveEntityCount++;
gTotalEntityMemory += [self oo_objectSize];
#endif
return self;
}
- (void) dealloc
{
[UNIVERSE ensureEntityReallyRemoved:self];
DESTROY(collidingEntities);
DESTROY(collisionRegion);
[self deleteJSSelf];
[self setOwner:nil];
[atmosphereFogging release];
#ifndef NDEBUG
gLiveEntityCount--;
gTotalEntityMemory -= [self oo_objectSize];
#endif
[super dealloc];
}
- (NSString *)descriptionComponents
{
return [NSString stringWithFormat:@"position: %@ scanClass: %@ status: %@", HPVectorDescription([self position]), OOStringFromScanClass([self scanClass]), OOStringFromEntityStatus([self status])];
}
- (NSUInteger) sessionID
{
return _sessionID;
}
- (BOOL)isShip
{
return isShip;
}
- (BOOL)isDock
{
return NO;
}
- (BOOL)isStation
{
return isStation;
}
- (BOOL)isSubEntity
{
return isSubEntity;
}
- (BOOL)isPlayer
{
return isPlayer;
}
- (BOOL)isPlanet
{
return NO;
}
- (BOOL)isSun
{
return NO;
}
- (BOOL) isSunlit
{
return isSunlit;
}
- (BOOL) isStellarObject
{
return [self isPlanet] || [self isSun];
}
- (BOOL)isSky
{
return NO;
}
- (BOOL)isWormhole
{
return isWormhole;
}
- (BOOL) isEffect
{
return NO;
}
- (BOOL) isVisualEffect
{
return NO;
}
- (BOOL) isWaypoint
{
return NO;
}
- (BOOL) validForAddToUniverse
{
NSUInteger mySessionID = [self sessionID];
NSUInteger currentSessionID = [UNIVERSE sessionID];
if (EXPECT_NOT(mySessionID != currentSessionID))
{
OOLogERR(@"entity.invalidSession", @"Entity %@ from session %lu cannot be added to universe in session %lu. This is an internal error, please report it.", [self shortDescription], mySessionID, currentSessionID);
return NO;
}
return YES;
}
- (void) addToLinkedLists
{
#ifndef NDEBUG
if (gDebugFlags & DEBUG_LINKED_LISTS)
OOLog(kOOLogEntityAddToList, @"DEBUG adding entity %@ to linked lists", self);
#endif
//
// insert at the start
if (UNIVERSE)
{
x_previous = nil; x_next = UNIVERSE->x_list_start;
// move UP the list
while ((x_next)&&(x_next->position.x - x_next->collision_radius < position.x - collision_radius))
{
x_previous = x_next;
x_next = x_next->x_next;
}
if (x_next) x_next->x_previous = self;
if (x_previous) x_previous->x_next = self;
else UNIVERSE->x_list_start = self;
y_previous = nil; y_next = UNIVERSE->y_list_start;
// move UP the list
while ((y_next)&&(y_next->position.y - y_next->collision_radius < position.y - collision_radius))
{
y_previous = y_next;
y_next = y_next->y_next;
}
if (y_next) y_next->y_previous = self;
if (y_previous) y_previous->y_next = self;
else UNIVERSE->y_list_start = self;
z_previous = nil; z_next = UNIVERSE->z_list_start;
// move UP the list
while ((z_next)&&(z_next->position.z - z_next->collision_radius < position.z - collision_radius))
{
z_previous = z_next;
z_next = z_next->z_next;
}
if (z_next) z_next->z_previous = self;
if (z_previous) z_previous->z_next = self;
else UNIVERSE->z_list_start = self;
}
#ifndef NDEBUG
if (gDebugFlags & DEBUG_LINKED_LISTS)
{
if (![self checkLinkedLists])
{
OOLog(kOOLogEntityAddToListError, @"DEBUG LINKED LISTS - problem encountered while adding %@ to linked lists", self);
[UNIVERSE debugDumpEntities];
}
}
#endif
}
- (void) removeFromLinkedLists
{
#ifndef NDEBUG
if (gDebugFlags & DEBUG_LINKED_LISTS)
OOLog(kOOLogEntityRemoveFromList, @"DEBUG removing entity %@ from linked lists", self);
#endif
if ((x_next == nil)&&(x_previous == nil)) // removed already!
return;
// make sure the starting point is still correct
if (UNIVERSE)
{
if ((UNIVERSE->x_list_start == self)&&(x_next))
UNIVERSE->x_list_start = x_next;
if ((UNIVERSE->y_list_start == self)&&(y_next))
UNIVERSE->y_list_start = y_next;
if ((UNIVERSE->z_list_start == self)&&(z_next))
UNIVERSE->z_list_start = z_next;
}
//
if (x_previous) x_previous->x_next = x_next;
if (x_next) x_next->x_previous = x_previous;
//
if (y_previous) y_previous->y_next = y_next;
if (y_next) y_next->y_previous = y_previous;
//
if (z_previous) z_previous->z_next = z_next;
if (z_next) z_next->z_previous = z_previous;
//
x_previous = nil; x_next = nil;
y_previous = nil; y_next = nil;
z_previous = nil; z_next = nil;
#ifndef NDEBUG
if (gDebugFlags & DEBUG_LINKED_LISTS)
{
if (![self checkLinkedLists])
{
OOLog(kOOLogEntityRemoveFromListError, @"DEBUG LINKED LISTS - problem encountered while removing %@ from linked lists", self);
[UNIVERSE debugDumpEntities];
}
}
#endif
}
- (BOOL) checkLinkedLists
{
// DEBUG check for loops
if (UNIVERSE->n_entities > 0)
{
int n;
Entity *check, *last;
//
last = nil;
//
n = UNIVERSE->n_entities;
check = UNIVERSE->x_list_start;
while ((n--)&&(check))
{
last = check;
check = check->x_next;
}
if ((check)||(n > 0))
{
OOLog(kOOLogEntityVerificationError, @"Broken x_next %@ list (%d) ***", UNIVERSE->x_list_start, n);
return NO;
}
//
n = UNIVERSE->n_entities;
check = last;
while ((n--)&&(check)) check = check->x_previous;
if ((check)||(n > 0))
{
OOLog(kOOLogEntityVerificationError, @"Broken x_previous %@ list (%d) ***", UNIVERSE->x_list_start, n);
return NO;
}
//
n = UNIVERSE->n_entities;
check = UNIVERSE->y_list_start;
while ((n--)&&(check))
{
last = check;
check = check->y_next;
}
if ((check)||(n > 0))
{
OOLog(kOOLogEntityVerificationError, @"Broken y_next %@ list (%d) ***", UNIVERSE->y_list_start, n);
return NO;
}
//
n = UNIVERSE->n_entities;
check = last;
while ((n--)&&(check)) check = check->y_previous;
if ((check)||(n > 0))
{
OOLog(kOOLogEntityVerificationError, @"Broken y_previous %@ list (%d) ***", UNIVERSE->y_list_start, n);
return NO;
}
//
n = UNIVERSE->n_entities;
check = UNIVERSE->z_list_start;
while ((n--)&&(check))
{
last = check;
check = check->z_next;
}
if ((check)||(n > 0))
{
OOLog(kOOLogEntityVerificationError, @"Broken z_next %@ list (%d) ***", UNIVERSE->z_list_start, n);
return NO;
}
//
n = UNIVERSE->n_entities;
check = last;
while ((n--)&&(check)) check = check->z_previous;
if ((check)||(n > 0))
{
OOLog(kOOLogEntityVerificationError, @"Broken z_previous %@ list (%d) ***", UNIVERSE->z_list_start, n);
return NO;
}
}
return YES;
}
- (void) updateLinkedLists
{
if (!UNIVERSE)
return; // not in the UNIVERSE - don't do this!
if ((x_next == nil)&&(x_previous == nil))
return; // not in the lists - don't do this!
#ifndef NDEBUG
if (gDebugFlags & DEBUG_LINKED_LISTS)
{
if (![self checkLinkedLists])
{
OOLog(kOOLogEntityVerificationError, @"DEBUG LINKED LISTS problem encountered before updating linked lists for %@", self);
[UNIVERSE debugDumpEntities];
}
}
#endif
// update position in linked list for position.x
// take self out of list..
if (x_previous) x_previous->x_next = x_next;
if (x_next) x_next->x_previous = x_previous;
// sink DOWN the list
while ((x_previous)&&(x_previous->position.x - x_previous->collision_radius > position.x - collision_radius))
{
x_next = x_previous;
x_previous = x_previous->x_previous;
}
// bubble UP the list
while ((x_next)&&(x_next->position.x - x_next->collision_radius < position.x - collision_radius))
{
x_previous = x_next;
x_next = x_next->x_next;
}
if (x_next) // insert self into the list before x_next..
x_next->x_previous = self;
if (x_previous) // insert self into the list after x_previous..
x_previous->x_next = self;
if ((x_previous == nil)&&(UNIVERSE)) // if we're the first then tell the UNIVERSE!
UNIVERSE->x_list_start = self;
// update position in linked list for position.y
// take self out of list..
if (y_previous) y_previous->y_next = y_next;
if (y_next) y_next->y_previous = y_previous;
// sink DOWN the list
while ((y_previous)&&(y_previous->position.y - y_previous->collision_radius > position.y - collision_radius))
{
y_next = y_previous;
y_previous = y_previous->y_previous;
}
// bubble UP the list
while ((y_next)&&(y_next->position.y - y_next->collision_radius < position.y - collision_radius))
{
y_previous = y_next;
y_next = y_next->y_next;
}
if (y_next) // insert self into the list before y_next..
y_next->y_previous = self;
if (y_previous) // insert self into the list after y_previous..
y_previous->y_next = self;
if ((y_previous == nil)&&(UNIVERSE)) // if we're the first then tell the UNIVERSE!
UNIVERSE->y_list_start = self;
// update position in linked list for position.z
// take self out of list..
if (z_previous) z_previous->z_next = z_next;
if (z_next) z_next->z_previous = z_previous;
// sink DOWN the list
while ((z_previous)&&(z_previous->position.z - z_previous->collision_radius > position.z - collision_radius))
{
z_next = z_previous;
z_previous = z_previous->z_previous;
}
// bubble UP the list
while ((z_next)&&(z_next->position.z - z_next->collision_radius < position.z - collision_radius))
{
z_previous = z_next;
z_next = z_next->z_next;
}
if (z_next) // insert self into the list before z_next..
z_next->z_previous = self;
if (z_previous) // insert self into the list after z_previous..
z_previous->z_next = self;
if ((z_previous == nil)&&(UNIVERSE)) // if we're the first then tell the UNIVERSE!
UNIVERSE->z_list_start = self;
// done
#ifndef NDEBUG
if (gDebugFlags & DEBUG_LINKED_LISTS)
{
if (![self checkLinkedLists])
{
OOLog(kOOLogEntityUpdateError, @"DEBUG LINKED LISTS problem encountered after updating linked lists for %@", self);
[UNIVERSE debugDumpEntities];
}
}
#endif
}
- (void) wasAddedToUniverse
{
// Do nothing
}
- (void) wasRemovedFromUniverse
{
// Do nothing
}
- (void) warnAboutHostiles
{
// do nothing for now, this can be expanded in sub classes
OOLog(@"general.error.subclassResponsibility.Entity-warnAboutHostiles", @"%@", @"***** Entity does nothing in warnAboutHostiles");
}
- (CollisionRegion*) collisionRegion
{
return collisionRegion;
}
- (void) setCollisionRegion: (CollisionRegion*) region
{
if (collisionRegion) [collisionRegion release];
collisionRegion = [region retain];
}
- (void) setUniversalID:(OOUniversalID)uid
{
universalID = uid;
}
- (OOUniversalID) universalID
{
return universalID;
}
- (BOOL) throwingSparks
{
return throw_sparks;
}
- (void) setThrowSparks:(BOOL) value
{
throw_sparks = value;
}
- (void) throwSparks
{
// do nothing for now
}
- (void) setOwner:(Entity *)ent
{
[_owner release];
_owner = [ent weakRetain];
}
- (id) owner
{
return [_owner weakRefUnderlyingObject];
}
- (ShipEntity *)parentEntity
{
id owner = [self owner];
if ([owner isShipWithSubEntityShip:self]) return owner;
return nil;
}
- (id<OOWeakReferenceSupport>) superShaderBindingTarget
{
return [self parentEntity];
}
- (ShipEntity *) rootShipEntity
{
ShipEntity *parent = [self parentEntity];
if (parent != nil) return [parent rootShipEntity];
if ([self isShip]) return (ShipEntity *)self;
return nil;
}
- (HPVector) position
{
return position;
}
- (Vector) cameraRelativePosition
{
return cameraRelativePosition;
}
- (GLfloat) cameraRangeFront
{
return magnitude(cameraRelativePosition) - [self frustumRadius];
}
- (GLfloat) cameraRangeBack
{
return magnitude(cameraRelativePosition) + [self frustumRadius];
}
// Exposed to uniform bindings.
// so needs to remain at OpenGL precision levels
- (Vector) relativePosition
{
return HPVectorToVector(HPvector_subtract([self position], [PLAYER position]));
}
- (Vector) vectorTo:(Entity *)entity
{
return HPVectorToVector(HPvector_subtract([entity position], [self position]));
}
- (void) setPosition:(HPVector) posn
{
position = posn;
[self updateCameraRelativePosition];
}
- (void) setPositionX:(OOHPScalar)x y:(OOHPScalar)y z:(OOHPScalar)z
{
position.x = x;
position.y = y;
position.z = z;
[self updateCameraRelativePosition];
}
- (void) updateCameraRelativePosition
{
cameraRelativePosition = HPVectorToVector(HPvector_subtract([self absolutePositionForSubentity],[PLAYER viewpointPosition]));
}
- (HPVector) absolutePositionForSubentity
{
return [self absolutePositionForSubentityOffset:kZeroHPVector];
}
- (HPVector) absolutePositionForSubentityOffset:(HPVector) offset
{
HPVector abspos = HPvector_add(position, OOHPVectorMultiplyMatrix(offset, rotMatrix));
Entity *last = nil;
Entity *father = [self parentEntity];
while (father != nil && father != last)
{
abspos = HPvector_add(OOHPVectorMultiplyMatrix(abspos, [father drawRotationMatrix]), [father position]);
last = father;
if (![last isSubEntity]) break;
father = [father owner];
}
return abspos;
}
- (double) zeroDistance
{
return zero_distance;
}
- (double) camZeroDistance
{
return cam_zero_distance;
}
- (NSComparisonResult) compareZeroDistance:(Entity *)otherEntity
{
if ((otherEntity)&&(zero_distance > otherEntity->zero_distance))
return NSOrderedAscending;
else
return NSOrderedDescending;
}
- (BoundingBox) boundingBox
{
return boundingBox;
}
- (GLfloat) mass
{
return mass;
}
- (void) setOrientation:(Quaternion) quat
{
orientation = quat;
[self orientationChanged];
}
- (Quaternion) orientation
{
return orientation;
}
- (Quaternion) normalOrientation
{
return [self orientation];
}
- (void) setNormalOrientation:(Quaternion) quat
{
[self setOrientation:quat];
}
- (void) orientationChanged
{
quaternion_normalize(&orientation);
rotMatrix = OOMatrixForQuaternionRotation(orientation);
}
- (void) setVelocity:(Vector) vel
{
velocity = vel;
}
- (Vector) velocity
{
return velocity;
}
- (double) speed
{
return magnitude([self velocity]);
}
- (GLfloat) distanceTravelled
{
return distanceTravelled;
}
- (void) setDistanceTravelled: (GLfloat) value
{
distanceTravelled = value;
}
- (void) setStatus:(OOEntityStatus) stat
{
_status = stat;
}
- (OOEntityStatus) status
{
return _status;
}
- (void) setScanClass:(OOScanClass)sClass
{
scanClass = sClass;
}
- (OOScanClass) scanClass
{
return scanClass;
}
- (void) setEnergy:(GLfloat) amount
{
energy = amount;
}
- (GLfloat) energy
{
return energy;
}
- (void) setMaxEnergy:(GLfloat)amount
{
maxEnergy = amount;
}
- (GLfloat) maxEnergy
{
return maxEnergy;
}
- (void) applyRoll:(GLfloat) roll andClimb:(GLfloat) climb
{
if ((roll == 0.0)&&(climb == 0.0)&&(!hasRotated))
return;
if (roll)
quaternion_rotate_about_z(&orientation, -roll);
if (climb)
quaternion_rotate_about_x(&orientation, -climb);
[self orientationChanged];
}
- (void) applyRoll:(GLfloat) roll climb:(GLfloat) climb andYaw:(GLfloat) yaw
{
if ((roll == 0.0)&&(climb == 0.0)&&(yaw == 0.0)&&(!hasRotated))
return;
if (roll)
quaternion_rotate_about_z(&orientation, -roll);
if (climb)
quaternion_rotate_about_x(&orientation, -climb);
if (yaw)
quaternion_rotate_about_y(&orientation, -yaw);
[self orientationChanged];
}
- (void) moveForward:(double)amount
{
HPVector forward = HPvector_multiply_scalar(HPvector_forward_from_quaternion(orientation), amount);
position = HPvector_add(position, forward);
distanceTravelled += amount;
}
- (OOMatrix) rotationMatrix
{
return rotMatrix;
}
- (OOMatrix) drawRotationMatrix
{
return rotMatrix;
}
- (OOMatrix) transformationMatrix
{
OOMatrix result = rotMatrix;
return OOMatrixHPTranslate(result, position);
}
- (OOMatrix) drawTransformationMatrix
{
OOMatrix result = rotMatrix;
return OOMatrixHPTranslate(result, position);
}
- (BOOL) canCollide
{
return YES;
}
- (GLfloat) collisionRadius
{
return collision_radius;
}
- (GLfloat) frustumRadius
{
return collision_radius;
}
- (void) setCollisionRadius:(GLfloat) amount
{
collision_radius = amount;
}
- (NSMutableArray *) collisionArray
{
return collidingEntities;
}
- (void) update:(OOTimeDelta)delta_t
{
if (_status != STATUS_COCKPIT_DISPLAY)
{
if ([self isSubEntity])
{
zero_distance = [[self owner] zeroDistance];
cam_zero_distance = [[self owner] camZeroDistance];
[self updateCameraRelativePosition];
}
else
{
zero_distance = HPdistance2(PLAYER->position, position);
cam_zero_distance = HPdistance2([PLAYER viewpointPosition], position);
[self updateCameraRelativePosition];
}
}
else
{
zero_distance = HPmagnitude2(position);
cam_zero_distance = zero_distance;
cameraRelativePosition = HPVectorToVector(position);
}
if ([self status] != STATUS_COCKPIT_DISPLAY)
{
[self applyVelocity:delta_t];
}
hasMoved = !HPvector_equal(position, lastPosition);
hasRotated = !quaternion_equal(orientation, lastOrientation);
lastPosition = position;
lastOrientation = orientation;
}
- (void) applyVelocity:(OOTimeDelta)delta_t
{
position = HPvector_add(position, HPvector_multiply_scalar(vectorToHPVector(velocity), delta_t));
}
- (BOOL) checkCloseCollisionWith:(Entity *)other
{
return other != nil;
}
- (double)findCollisionRadius
{
OOLogGenericSubclassResponsibility();
return 0;
}
- (void) drawImmediate:(bool)immediate translucent:(bool)translucent
{
OOLogGenericSubclassResponsibility();
}
- (void) takeEnergyDamage:(double) amount from:(Entity *) ent becauseOf:(Entity *) other weaponIdentifier:(NSString *)weaponIdentifier
{
}
- (void)dumpState
{
if (OOLogWillDisplayMessagesInClass(@"dumpState"))
{
OOLog(@"dumpState", @"State for %@:", self);
OOLogPushIndent();
OOLogIndent();
@try
{
[self dumpSelfState];
}
@catch (id exception) {}
OOLogPopIndent();
}
}
- (void)dumpSelfState
{
NSMutableArray *flags = nil;
NSString *flagsString = nil;
id owner = [self owner];
if (owner == self) owner = @"self";
else if (owner == nil) owner = @"none";
OOLog(@"dumpState.entity", @"Universal ID: %u", universalID);
OOLog(@"dumpState.entity", @"Scan class: %@", OOStringFromScanClass(scanClass));
OOLog(@"dumpState.entity", @"Status: %@", OOStringFromEntityStatus([self status]));
OOLog(@"dumpState.entity", @"Position: %@", HPVectorDescription(position));
OOLog(@"dumpState.entity", @"Orientation: %@", QuaternionDescription(orientation));
OOLog(@"dumpState.entity", @"Distance travelled: %g", distanceTravelled);
OOLog(@"dumpState.entity", @"Energy: %g of %g", energy, maxEnergy);
OOLog(@"dumpState.entity", @"Mass: %g", mass);
OOLog(@"dumpState.entity", @"Owner: %@", owner);
flags = [NSMutableArray array];
#define ADD_FLAG_IF_SET(x) if (x) { [flags addObject:@#x]; }
ADD_FLAG_IF_SET(isShip);
ADD_FLAG_IF_SET(isStation);
ADD_FLAG_IF_SET(isPlayer);
ADD_FLAG_IF_SET(isWormhole);
ADD_FLAG_IF_SET(isSubEntity);
ADD_FLAG_IF_SET(hasMoved);
ADD_FLAG_IF_SET(hasRotated);
ADD_FLAG_IF_SET(isSunlit);
ADD_FLAG_IF_SET(throw_sparks);
flagsString = [flags count] ? [flags componentsJoinedByString:@", "] : (NSString *)@"none";
OOLog(@"dumpState.entity", @"Flags: %@", flagsString);
OOLog(@"dumpState.entity", @"Collision Test Filter: %u", collisionTestFilter);
}
- (void)subEntityReallyDied:(ShipEntity *)sub
{
OOLog(@"entity.bug", @"%s called for non-ship entity %p by %p", __PRETTY_FUNCTION__, self, sub);
}
// For shader bindings.
- (GLfloat)universalTime
{
return [UNIVERSE getTime];
}
- (GLfloat)spawnTime
{
return spawnTime;
}
- (GLfloat)timeElapsedSinceSpawn
{
return [UNIVERSE getTime] - spawnTime;
}
- (void) setAtmosphereFogging: (OOColor *)fogging
{
[atmosphereFogging release];
atmosphereFogging = [fogging retain];
}
- (OOColor *) fogUniform
{
return [[atmosphereFogging retain] autorelease];
}
#ifndef NDEBUG
- (NSString *) descriptionForObjDumpBasic
{
NSString *result = [self descriptionComponents];
if (result != nil) result = [NSString stringWithFormat:@"%@ %@", NSStringFromClass([self class]), result];
else result = [self description];
return result;
}
- (NSString *) descriptionForObjDump
{
NSString *result = [self descriptionForObjDumpBasic];
result = [result stringByAppendingFormat:@" range: %g (visible: %@)", HPdistance([self position], [PLAYER position]), [self isVisible] ? @"yes" : @"no"];
return result;
}
- (NSSet *) allTextures
{
return nil;
}
#endif
- (BOOL) isVisible
{
return cam_zero_distance <= ABSOLUTE_NO_DRAW_DISTANCE2;
}
- (BOOL) isInSpace
{
switch ([self status])
{
case STATUS_IN_FLIGHT:
case STATUS_DOCKING:
case STATUS_LAUNCHING:
case STATUS_AUTOPILOT_ENGAGED:
case STATUS_WITCHSPACE_COUNTDOWN:
case STATUS_BEING_SCOOPED:
case STATUS_EFFECT:
case STATUS_ACTIVE:
return YES;
default:
return NO;
}
}
- (BOOL) isImmuneToBreakPatternHide
{
return isImmuneToBreakPatternHide;
}
@end