Line data Source code
1 0 : /*
2 :
3 : Entity.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "Entity.h"
26 : #import "EntityOOJavaScriptExtensions.h"
27 : #import "PlayerEntity.h"
28 : #import "OOPlanetEntity.h"
29 :
30 : #import "OOMaths.h"
31 : #import "Universe.h"
32 : #import "GameController.h"
33 : #import "ResourceManager.h"
34 : #import "OOConstToString.h"
35 :
36 : #import "CollisionRegion.h"
37 :
38 : #import "NSScannerOOExtensions.h"
39 : #import "OODebugFlags.h"
40 : #import "NSObjectOOExtensions.h"
41 :
42 : #ifndef NDEBUG
43 0 : uint32_t gLiveEntityCount = 0;
44 0 : size_t gTotalEntityMemory = 0;
45 : #endif
46 :
47 :
48 : #ifndef NDEBUG
49 0 : static NSString * const kOOLogEntityAddToList = @"entity.linkedList.add";
50 0 : static NSString * const kOOLogEntityAddToListError = @"entity.linkedList.add.error";
51 0 : static NSString * const kOOLogEntityRemoveFromList = @"entity.linkedList.remove";
52 0 : static NSString * const kOOLogEntityRemoveFromListError = @"entity.linkedList.remove.error";
53 0 : static NSString * const kOOLogEntityUpdateError = @"entity.linkedList.update.error";
54 : #endif
55 0 : static NSString * const kOOLogEntityVerificationError = @"entity.linkedList.verify.error";
56 :
57 :
58 :
59 : @interface Entity (OOPrivate)
60 :
61 0 : - (BOOL) checkLinkedLists;
62 :
63 : @end
64 :
65 :
66 : @implementation Entity
67 :
68 0 : - (id) init
69 : {
70 : self = [super init];
71 : if (EXPECT_NOT(self == nil)) return nil;
72 :
73 : _sessionID = [UNIVERSE sessionID];
74 :
75 : orientation = kIdentityQuaternion;
76 : rotMatrix = kIdentityMatrix;
77 : position = kZeroHPVector;
78 :
79 : no_draw_distance = 100000.0; // 10 km
80 :
81 : collidingEntities = [[NSMutableArray alloc] init];
82 :
83 : scanClass = CLASS_NOT_SET;
84 : [self setStatus:STATUS_COCKPIT_DISPLAY];
85 :
86 : spawnTime = [UNIVERSE getTime];
87 :
88 : isSunlit = YES;
89 :
90 : atmosphereFogging = [[OOColor colorWithRed: 0.0 green: 0.0 blue: 0.0 alpha: 0.0] retain];
91 :
92 : #ifndef NDEBUG
93 : gLiveEntityCount++;
94 : gTotalEntityMemory += [self oo_objectSize];
95 : #endif
96 :
97 : return self;
98 : }
99 :
100 :
101 0 : - (void) dealloc
102 : {
103 : [UNIVERSE ensureEntityReallyRemoved:self];
104 : DESTROY(collidingEntities);
105 : DESTROY(collisionRegion);
106 : [self deleteJSSelf];
107 : [self setOwner:nil];
108 : [atmosphereFogging release];
109 :
110 : #ifndef NDEBUG
111 : gLiveEntityCount--;
112 : gTotalEntityMemory -= [self oo_objectSize];
113 : #endif
114 :
115 : [super dealloc];
116 : }
117 :
118 :
119 0 : - (NSString *)descriptionComponents
120 : {
121 : return [NSString stringWithFormat:@"position: %@ scanClass: %@ status: %@", HPVectorDescription([self position]), OOStringFromScanClass([self scanClass]), OOStringFromEntityStatus([self status])];
122 : }
123 :
124 :
125 : - (NSUInteger) sessionID
126 : {
127 : return _sessionID;
128 : }
129 :
130 :
131 : - (BOOL)isShip
132 : {
133 : return isShip;
134 : }
135 :
136 :
137 : - (BOOL)isDock
138 : {
139 : return NO;
140 : }
141 :
142 :
143 : - (BOOL)isStation
144 : {
145 : return isStation;
146 : }
147 :
148 :
149 : - (BOOL)isSubEntity
150 : {
151 : return isSubEntity;
152 : }
153 :
154 :
155 : - (BOOL)isPlayer
156 : {
157 : return isPlayer;
158 : }
159 :
160 :
161 : - (BOOL)isPlanet
162 : {
163 : return NO;
164 : }
165 :
166 :
167 : - (BOOL)isSun
168 : {
169 : return NO;
170 : }
171 :
172 :
173 : - (BOOL) isSunlit
174 : {
175 : return isSunlit;
176 : }
177 :
178 :
179 : - (BOOL) isStellarObject
180 : {
181 : return [self isPlanet] || [self isSun];
182 : }
183 :
184 :
185 : - (BOOL)isSky
186 : {
187 : return NO;
188 : }
189 :
190 : - (BOOL)isWormhole
191 : {
192 : return isWormhole;
193 : }
194 :
195 :
196 : - (BOOL) isEffect
197 : {
198 : return NO;
199 : }
200 :
201 :
202 : - (BOOL) isVisualEffect
203 : {
204 : return NO;
205 : }
206 :
207 :
208 : - (BOOL) isWaypoint
209 : {
210 : return NO;
211 : }
212 :
213 :
214 : - (BOOL) validForAddToUniverse
215 : {
216 : NSUInteger mySessionID = [self sessionID];
217 : NSUInteger currentSessionID = [UNIVERSE sessionID];
218 : if (EXPECT_NOT(mySessionID != currentSessionID))
219 : {
220 : 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);
221 : return NO;
222 : }
223 :
224 : return YES;
225 : }
226 :
227 :
228 : - (void) addToLinkedLists
229 : {
230 : #ifndef NDEBUG
231 : if (gDebugFlags & DEBUG_LINKED_LISTS)
232 : OOLog(kOOLogEntityAddToList, @"DEBUG adding entity %@ to linked lists", self);
233 : #endif
234 : //
235 : // insert at the start
236 : if (UNIVERSE)
237 : {
238 : x_previous = nil; x_next = UNIVERSE->x_list_start;
239 : // move UP the list
240 : while ((x_next)&&(x_next->position.x - x_next->collision_radius < position.x - collision_radius))
241 : {
242 : x_previous = x_next;
243 : x_next = x_next->x_next;
244 : }
245 : if (x_next) x_next->x_previous = self;
246 : if (x_previous) x_previous->x_next = self;
247 : else UNIVERSE->x_list_start = self;
248 :
249 : y_previous = nil; y_next = UNIVERSE->y_list_start;
250 : // move UP the list
251 : while ((y_next)&&(y_next->position.y - y_next->collision_radius < position.y - collision_radius))
252 : {
253 : y_previous = y_next;
254 : y_next = y_next->y_next;
255 : }
256 : if (y_next) y_next->y_previous = self;
257 : if (y_previous) y_previous->y_next = self;
258 : else UNIVERSE->y_list_start = self;
259 :
260 : z_previous = nil; z_next = UNIVERSE->z_list_start;
261 : // move UP the list
262 : while ((z_next)&&(z_next->position.z - z_next->collision_radius < position.z - collision_radius))
263 : {
264 : z_previous = z_next;
265 : z_next = z_next->z_next;
266 : }
267 : if (z_next) z_next->z_previous = self;
268 : if (z_previous) z_previous->z_next = self;
269 : else UNIVERSE->z_list_start = self;
270 :
271 : }
272 :
273 : #ifndef NDEBUG
274 : if (gDebugFlags & DEBUG_LINKED_LISTS)
275 : {
276 : if (![self checkLinkedLists])
277 : {
278 : OOLog(kOOLogEntityAddToListError, @"DEBUG LINKED LISTS - problem encountered while adding %@ to linked lists", self);
279 : [UNIVERSE debugDumpEntities];
280 : }
281 : }
282 : #endif
283 : }
284 :
285 :
286 : - (void) removeFromLinkedLists
287 : {
288 : #ifndef NDEBUG
289 : if (gDebugFlags & DEBUG_LINKED_LISTS)
290 : OOLog(kOOLogEntityRemoveFromList, @"DEBUG removing entity %@ from linked lists", self);
291 : #endif
292 :
293 : if ((x_next == nil)&&(x_previous == nil)) // removed already!
294 : return;
295 :
296 : // make sure the starting point is still correct
297 : if (UNIVERSE)
298 : {
299 : if ((UNIVERSE->x_list_start == self)&&(x_next))
300 : UNIVERSE->x_list_start = x_next;
301 : if ((UNIVERSE->y_list_start == self)&&(y_next))
302 : UNIVERSE->y_list_start = y_next;
303 : if ((UNIVERSE->z_list_start == self)&&(z_next))
304 : UNIVERSE->z_list_start = z_next;
305 : }
306 : //
307 : if (x_previous) x_previous->x_next = x_next;
308 : if (x_next) x_next->x_previous = x_previous;
309 : //
310 : if (y_previous) y_previous->y_next = y_next;
311 : if (y_next) y_next->y_previous = y_previous;
312 : //
313 : if (z_previous) z_previous->z_next = z_next;
314 : if (z_next) z_next->z_previous = z_previous;
315 : //
316 : x_previous = nil; x_next = nil;
317 : y_previous = nil; y_next = nil;
318 : z_previous = nil; z_next = nil;
319 :
320 : #ifndef NDEBUG
321 : if (gDebugFlags & DEBUG_LINKED_LISTS)
322 : {
323 : if (![self checkLinkedLists])
324 : {
325 : OOLog(kOOLogEntityRemoveFromListError, @"DEBUG LINKED LISTS - problem encountered while removing %@ from linked lists", self);
326 : [UNIVERSE debugDumpEntities];
327 : }
328 : }
329 : #endif
330 : }
331 :
332 :
333 0 : - (BOOL) checkLinkedLists
334 : {
335 : // DEBUG check for loops
336 : if (UNIVERSE->n_entities > 0)
337 : {
338 : int n;
339 : Entity *check, *last;
340 : //
341 : last = nil;
342 : //
343 : n = UNIVERSE->n_entities;
344 : check = UNIVERSE->x_list_start;
345 : while ((n--)&&(check))
346 : {
347 : last = check;
348 : check = check->x_next;
349 : }
350 : if ((check)||(n > 0))
351 : {
352 : OOLog(kOOLogEntityVerificationError, @"Broken x_next %@ list (%d) ***", UNIVERSE->x_list_start, n);
353 : return NO;
354 : }
355 : //
356 : n = UNIVERSE->n_entities;
357 : check = last;
358 : while ((n--)&&(check)) check = check->x_previous;
359 : if ((check)||(n > 0))
360 : {
361 : OOLog(kOOLogEntityVerificationError, @"Broken x_previous %@ list (%d) ***", UNIVERSE->x_list_start, n);
362 : return NO;
363 : }
364 : //
365 : n = UNIVERSE->n_entities;
366 : check = UNIVERSE->y_list_start;
367 : while ((n--)&&(check))
368 : {
369 : last = check;
370 : check = check->y_next;
371 : }
372 : if ((check)||(n > 0))
373 : {
374 : OOLog(kOOLogEntityVerificationError, @"Broken y_next %@ list (%d) ***", UNIVERSE->y_list_start, n);
375 : return NO;
376 : }
377 : //
378 : n = UNIVERSE->n_entities;
379 : check = last;
380 : while ((n--)&&(check)) check = check->y_previous;
381 : if ((check)||(n > 0))
382 : {
383 : OOLog(kOOLogEntityVerificationError, @"Broken y_previous %@ list (%d) ***", UNIVERSE->y_list_start, n);
384 : return NO;
385 : }
386 : //
387 : n = UNIVERSE->n_entities;
388 : check = UNIVERSE->z_list_start;
389 : while ((n--)&&(check))
390 : {
391 : last = check;
392 : check = check->z_next;
393 : }
394 : if ((check)||(n > 0))
395 : {
396 : OOLog(kOOLogEntityVerificationError, @"Broken z_next %@ list (%d) ***", UNIVERSE->z_list_start, n);
397 : return NO;
398 : }
399 : //
400 : n = UNIVERSE->n_entities;
401 : check = last;
402 : while ((n--)&&(check)) check = check->z_previous;
403 : if ((check)||(n > 0))
404 : {
405 : OOLog(kOOLogEntityVerificationError, @"Broken z_previous %@ list (%d) ***", UNIVERSE->z_list_start, n);
406 : return NO;
407 : }
408 : }
409 : return YES;
410 : }
411 :
412 :
413 : - (void) updateLinkedLists
414 : {
415 : if (!UNIVERSE)
416 : return; // not in the UNIVERSE - don't do this!
417 : if ((x_next == nil)&&(x_previous == nil))
418 : return; // not in the lists - don't do this!
419 :
420 : #ifndef NDEBUG
421 : if (gDebugFlags & DEBUG_LINKED_LISTS)
422 : {
423 : if (![self checkLinkedLists])
424 : {
425 : OOLog(kOOLogEntityVerificationError, @"DEBUG LINKED LISTS problem encountered before updating linked lists for %@", self);
426 : [UNIVERSE debugDumpEntities];
427 : }
428 : }
429 : #endif
430 :
431 : // update position in linked list for position.x
432 : // take self out of list..
433 : if (x_previous) x_previous->x_next = x_next;
434 : if (x_next) x_next->x_previous = x_previous;
435 : // sink DOWN the list
436 : while ((x_previous)&&(x_previous->position.x - x_previous->collision_radius > position.x - collision_radius))
437 : {
438 : x_next = x_previous;
439 : x_previous = x_previous->x_previous;
440 : }
441 : // bubble UP the list
442 : while ((x_next)&&(x_next->position.x - x_next->collision_radius < position.x - collision_radius))
443 : {
444 : x_previous = x_next;
445 : x_next = x_next->x_next;
446 : }
447 : if (x_next) // insert self into the list before x_next..
448 : x_next->x_previous = self;
449 : if (x_previous) // insert self into the list after x_previous..
450 : x_previous->x_next = self;
451 : if ((x_previous == nil)&&(UNIVERSE)) // if we're the first then tell the UNIVERSE!
452 : UNIVERSE->x_list_start = self;
453 :
454 : // update position in linked list for position.y
455 : // take self out of list..
456 : if (y_previous) y_previous->y_next = y_next;
457 : if (y_next) y_next->y_previous = y_previous;
458 : // sink DOWN the list
459 : while ((y_previous)&&(y_previous->position.y - y_previous->collision_radius > position.y - collision_radius))
460 : {
461 : y_next = y_previous;
462 : y_previous = y_previous->y_previous;
463 : }
464 : // bubble UP the list
465 : while ((y_next)&&(y_next->position.y - y_next->collision_radius < position.y - collision_radius))
466 : {
467 : y_previous = y_next;
468 : y_next = y_next->y_next;
469 : }
470 : if (y_next) // insert self into the list before y_next..
471 : y_next->y_previous = self;
472 : if (y_previous) // insert self into the list after y_previous..
473 : y_previous->y_next = self;
474 : if ((y_previous == nil)&&(UNIVERSE)) // if we're the first then tell the UNIVERSE!
475 : UNIVERSE->y_list_start = self;
476 :
477 : // update position in linked list for position.z
478 : // take self out of list..
479 : if (z_previous) z_previous->z_next = z_next;
480 : if (z_next) z_next->z_previous = z_previous;
481 : // sink DOWN the list
482 : while ((z_previous)&&(z_previous->position.z - z_previous->collision_radius > position.z - collision_radius))
483 : {
484 : z_next = z_previous;
485 : z_previous = z_previous->z_previous;
486 : }
487 : // bubble UP the list
488 : while ((z_next)&&(z_next->position.z - z_next->collision_radius < position.z - collision_radius))
489 : {
490 : z_previous = z_next;
491 : z_next = z_next->z_next;
492 : }
493 : if (z_next) // insert self into the list before z_next..
494 : z_next->z_previous = self;
495 : if (z_previous) // insert self into the list after z_previous..
496 : z_previous->z_next = self;
497 : if ((z_previous == nil)&&(UNIVERSE)) // if we're the first then tell the UNIVERSE!
498 : UNIVERSE->z_list_start = self;
499 :
500 : // done
501 : #ifndef NDEBUG
502 : if (gDebugFlags & DEBUG_LINKED_LISTS)
503 : {
504 : if (![self checkLinkedLists])
505 : {
506 : OOLog(kOOLogEntityUpdateError, @"DEBUG LINKED LISTS problem encountered after updating linked lists for %@", self);
507 : [UNIVERSE debugDumpEntities];
508 : }
509 : }
510 : #endif
511 : }
512 :
513 :
514 : - (void) wasAddedToUniverse
515 : {
516 : // Do nothing
517 : }
518 :
519 :
520 : - (void) wasRemovedFromUniverse
521 : {
522 : // Do nothing
523 : }
524 :
525 :
526 : - (void) warnAboutHostiles
527 : {
528 : // do nothing for now, this can be expanded in sub classes
529 : OOLog(@"general.error.subclassResponsibility.Entity-warnAboutHostiles", @"%@", @"***** Entity does nothing in warnAboutHostiles");
530 : }
531 :
532 :
533 : - (CollisionRegion*) collisionRegion
534 : {
535 : return collisionRegion;
536 : }
537 :
538 :
539 : - (void) setCollisionRegion: (CollisionRegion*) region
540 : {
541 : if (collisionRegion) [collisionRegion release];
542 : collisionRegion = [region retain];
543 : }
544 :
545 :
546 : - (void) setUniversalID:(OOUniversalID)uid
547 : {
548 : universalID = uid;
549 : }
550 :
551 :
552 : - (OOUniversalID) universalID
553 : {
554 : return universalID;
555 : }
556 :
557 :
558 : - (BOOL) throwingSparks
559 : {
560 : return throw_sparks;
561 : }
562 :
563 :
564 : - (void) setThrowSparks:(BOOL) value
565 : {
566 : throw_sparks = value;
567 : }
568 :
569 :
570 : - (void) throwSparks
571 : {
572 : // do nothing for now
573 : }
574 :
575 :
576 : - (void) setOwner:(Entity *)ent
577 : {
578 : [_owner release];
579 : _owner = [ent weakRetain];
580 : }
581 :
582 :
583 : - (id) owner
584 : {
585 : return [_owner weakRefUnderlyingObject];
586 : }
587 :
588 :
589 : - (ShipEntity *)parentEntity
590 : {
591 : id owner = [self owner];
592 : if ([owner isShipWithSubEntityShip:self]) return owner;
593 : return nil;
594 : }
595 :
596 :
597 0 : - (id<OOWeakReferenceSupport>) superShaderBindingTarget
598 : {
599 : return [self parentEntity];
600 : }
601 :
602 :
603 : - (ShipEntity *) rootShipEntity
604 : {
605 : ShipEntity *parent = [self parentEntity];
606 : if (parent != nil) return [parent rootShipEntity];
607 : if ([self isShip]) return (ShipEntity *)self;
608 : return nil;
609 : }
610 :
611 :
612 : - (HPVector) position
613 : {
614 : return position;
615 : }
616 :
617 : - (Vector) cameraRelativePosition
618 : {
619 : return cameraRelativePosition;
620 : }
621 :
622 : - (GLfloat) cameraRangeFront
623 : {
624 : return magnitude(cameraRelativePosition) - [self frustumRadius];
625 : }
626 :
627 : - (GLfloat) cameraRangeBack
628 : {
629 : return magnitude(cameraRelativePosition) + [self frustumRadius];
630 : }
631 :
632 :
633 :
634 : // Exposed to uniform bindings.
635 : // so needs to remain at OpenGL precision levels
636 0 : - (Vector) relativePosition
637 : {
638 : return HPVectorToVector(HPvector_subtract([self position], [PLAYER position]));
639 : }
640 :
641 : - (Vector) vectorTo:(Entity *)entity
642 : {
643 : return HPVectorToVector(HPvector_subtract([entity position], [self position]));
644 : }
645 :
646 :
647 : - (void) setPosition:(HPVector) posn
648 : {
649 : position = posn;
650 : [self updateCameraRelativePosition];
651 : }
652 :
653 :
654 : - (void) setPositionX:(OOHPScalar)x y:(OOHPScalar)y z:(OOHPScalar)z
655 : {
656 : position.x = x;
657 : position.y = y;
658 : position.z = z;
659 : [self updateCameraRelativePosition];
660 : }
661 :
662 :
663 : - (void) updateCameraRelativePosition
664 : {
665 : cameraRelativePosition = HPVectorToVector(HPvector_subtract([self absolutePositionForSubentity],[PLAYER viewpointPosition]));
666 : }
667 :
668 :
669 : - (HPVector) absolutePositionForSubentity
670 : {
671 : return [self absolutePositionForSubentityOffset:kZeroHPVector];
672 : }
673 :
674 :
675 : - (HPVector) absolutePositionForSubentityOffset:(HPVector) offset
676 : {
677 : HPVector abspos = HPvector_add(position, OOHPVectorMultiplyMatrix(offset, rotMatrix));
678 : Entity *last = nil;
679 : Entity *father = [self parentEntity];
680 :
681 : while (father != nil && father != last)
682 : {
683 : abspos = HPvector_add(OOHPVectorMultiplyMatrix(abspos, [father drawRotationMatrix]), [father position]);
684 : last = father;
685 : if (![last isSubEntity]) break;
686 : father = [father owner];
687 : }
688 : return abspos;
689 : }
690 :
691 :
692 : - (double) zeroDistance
693 : {
694 : return zero_distance;
695 : }
696 :
697 :
698 : - (double) camZeroDistance
699 : {
700 : return cam_zero_distance;
701 : }
702 :
703 :
704 : - (NSComparisonResult) compareZeroDistance:(Entity *)otherEntity
705 : {
706 : if ((otherEntity)&&(zero_distance > otherEntity->zero_distance))
707 : return NSOrderedAscending;
708 : else
709 : return NSOrderedDescending;
710 : }
711 :
712 :
713 : - (BoundingBox) boundingBox
714 : {
715 : return boundingBox;
716 : }
717 :
718 :
719 : - (GLfloat) mass
720 : {
721 : return mass;
722 : }
723 :
724 :
725 : - (void) setOrientation:(Quaternion) quat
726 : {
727 : orientation = quat;
728 : [self orientationChanged];
729 : }
730 :
731 :
732 : - (Quaternion) orientation
733 : {
734 : return orientation;
735 : }
736 :
737 :
738 : - (Quaternion) normalOrientation
739 : {
740 : return [self orientation];
741 : }
742 :
743 :
744 : - (void) setNormalOrientation:(Quaternion) quat
745 : {
746 : [self setOrientation:quat];
747 : }
748 :
749 :
750 : - (void) orientationChanged
751 : {
752 : quaternion_normalize(&orientation);
753 : rotMatrix = OOMatrixForQuaternionRotation(orientation);
754 : }
755 :
756 :
757 : - (void) setVelocity:(Vector) vel
758 : {
759 : velocity = vel;
760 : }
761 :
762 :
763 : - (Vector) velocity
764 : {
765 : return velocity;
766 : }
767 :
768 :
769 : - (double) speed
770 : {
771 : return magnitude([self velocity]);
772 : }
773 :
774 :
775 : - (GLfloat) distanceTravelled
776 : {
777 : return distanceTravelled;
778 : }
779 :
780 :
781 : - (void) setDistanceTravelled: (GLfloat) value
782 : {
783 : distanceTravelled = value;
784 : }
785 :
786 :
787 : - (void) setStatus:(OOEntityStatus) stat
788 : {
789 : _status = stat;
790 : }
791 :
792 :
793 : - (OOEntityStatus) status
794 : {
795 : return _status;
796 : }
797 :
798 :
799 : - (void) setScanClass:(OOScanClass)sClass
800 : {
801 : scanClass = sClass;
802 : }
803 :
804 :
805 : - (OOScanClass) scanClass
806 : {
807 : return scanClass;
808 : }
809 :
810 :
811 : - (void) setEnergy:(GLfloat) amount
812 : {
813 : energy = amount;
814 : }
815 :
816 :
817 : - (GLfloat) energy
818 : {
819 : return energy;
820 : }
821 :
822 :
823 : - (void) setMaxEnergy:(GLfloat)amount
824 : {
825 : maxEnergy = amount;
826 : }
827 :
828 :
829 : - (GLfloat) maxEnergy
830 : {
831 : return maxEnergy;
832 : }
833 :
834 :
835 : - (void) applyRoll:(GLfloat) roll andClimb:(GLfloat) climb
836 : {
837 : if ((roll == 0.0)&&(climb == 0.0)&&(!hasRotated))
838 : return;
839 :
840 : if (roll)
841 : quaternion_rotate_about_z(&orientation, -roll);
842 : if (climb)
843 : quaternion_rotate_about_x(&orientation, -climb);
844 :
845 : [self orientationChanged];
846 : }
847 :
848 :
849 : - (void) applyRoll:(GLfloat) roll climb:(GLfloat) climb andYaw:(GLfloat) yaw
850 : {
851 : if ((roll == 0.0)&&(climb == 0.0)&&(yaw == 0.0)&&(!hasRotated))
852 : return;
853 :
854 : if (roll)
855 : quaternion_rotate_about_z(&orientation, -roll);
856 : if (climb)
857 : quaternion_rotate_about_x(&orientation, -climb);
858 : if (yaw)
859 : quaternion_rotate_about_y(&orientation, -yaw);
860 :
861 : [self orientationChanged];
862 : }
863 :
864 :
865 : - (void) moveForward:(double)amount
866 : {
867 : HPVector forward = HPvector_multiply_scalar(HPvector_forward_from_quaternion(orientation), amount);
868 : position = HPvector_add(position, forward);
869 : distanceTravelled += amount;
870 : }
871 :
872 :
873 : - (OOMatrix) rotationMatrix
874 : {
875 : return rotMatrix;
876 : }
877 :
878 :
879 : - (OOMatrix) drawRotationMatrix
880 : {
881 : return rotMatrix;
882 : }
883 :
884 :
885 : - (OOMatrix) transformationMatrix
886 : {
887 : OOMatrix result = rotMatrix;
888 : return OOMatrixHPTranslate(result, position);
889 : }
890 :
891 :
892 : - (OOMatrix) drawTransformationMatrix
893 : {
894 : OOMatrix result = rotMatrix;
895 : return OOMatrixHPTranslate(result, position);
896 : }
897 :
898 :
899 : - (BOOL) canCollide
900 : {
901 : return YES;
902 : }
903 :
904 :
905 : - (GLfloat) collisionRadius
906 : {
907 : return collision_radius;
908 : }
909 :
910 :
911 : - (GLfloat) frustumRadius
912 : {
913 : return collision_radius;
914 : }
915 :
916 :
917 : - (void) setCollisionRadius:(GLfloat) amount
918 : {
919 : collision_radius = amount;
920 : }
921 :
922 :
923 : - (NSMutableArray *) collisionArray
924 : {
925 : return collidingEntities;
926 : }
927 :
928 :
929 : - (void) update:(OOTimeDelta)delta_t
930 : {
931 : if (_status != STATUS_COCKPIT_DISPLAY)
932 : {
933 : if ([self isSubEntity])
934 : {
935 : zero_distance = [[self owner] zeroDistance];
936 : cam_zero_distance = [[self owner] camZeroDistance];
937 : [self updateCameraRelativePosition];
938 : }
939 : else
940 : {
941 : zero_distance = HPdistance2(PLAYER->position, position);
942 : cam_zero_distance = HPdistance2([PLAYER viewpointPosition], position);
943 : [self updateCameraRelativePosition];
944 : }
945 : }
946 : else
947 : {
948 : zero_distance = HPmagnitude2(position);
949 : cam_zero_distance = zero_distance;
950 : cameraRelativePosition = HPVectorToVector(position);
951 : }
952 :
953 : if ([self status] != STATUS_COCKPIT_DISPLAY)
954 : {
955 : [self applyVelocity:delta_t];
956 : }
957 :
958 : hasMoved = !HPvector_equal(position, lastPosition);
959 : hasRotated = !quaternion_equal(orientation, lastOrientation);
960 : lastPosition = position;
961 : lastOrientation = orientation;
962 : }
963 :
964 :
965 : - (void) applyVelocity:(OOTimeDelta)delta_t
966 : {
967 : position = HPvector_add(position, HPvector_multiply_scalar(vectorToHPVector(velocity), delta_t));
968 : }
969 :
970 :
971 : - (BOOL) checkCloseCollisionWith:(Entity *)other
972 : {
973 : return other != nil;
974 : }
975 :
976 :
977 : - (double)findCollisionRadius
978 : {
979 : OOLogGenericSubclassResponsibility();
980 : return 0;
981 : }
982 :
983 :
984 : - (void) drawImmediate:(bool)immediate translucent:(bool)translucent
985 : {
986 : OOLogGenericSubclassResponsibility();
987 : }
988 :
989 :
990 : - (void) takeEnergyDamage:(double) amount from:(Entity *) ent becauseOf:(Entity *) other weaponIdentifier:(NSString *)weaponIdentifier
991 : {
992 :
993 : }
994 :
995 :
996 : - (void)dumpState
997 : {
998 : if (OOLogWillDisplayMessagesInClass(@"dumpState"))
999 : {
1000 : OOLog(@"dumpState", @"State for %@:", self);
1001 : OOLogPushIndent();
1002 : OOLogIndent();
1003 : @try
1004 : {
1005 : [self dumpSelfState];
1006 : }
1007 : @catch (id exception) {}
1008 : OOLogPopIndent();
1009 : }
1010 : }
1011 :
1012 :
1013 : - (void)dumpSelfState
1014 : {
1015 : NSMutableArray *flags = nil;
1016 : NSString *flagsString = nil;
1017 : id owner = [self owner];
1018 :
1019 : if (owner == self) owner = @"self";
1020 : else if (owner == nil) owner = @"none";
1021 :
1022 : OOLog(@"dumpState.entity", @"Universal ID: %u", universalID);
1023 : OOLog(@"dumpState.entity", @"Scan class: %@", OOStringFromScanClass(scanClass));
1024 : OOLog(@"dumpState.entity", @"Status: %@", OOStringFromEntityStatus([self status]));
1025 : OOLog(@"dumpState.entity", @"Position: %@", HPVectorDescription(position));
1026 : OOLog(@"dumpState.entity", @"Orientation: %@", QuaternionDescription(orientation));
1027 : OOLog(@"dumpState.entity", @"Distance travelled: %g", distanceTravelled);
1028 : OOLog(@"dumpState.entity", @"Energy: %g of %g", energy, maxEnergy);
1029 : OOLog(@"dumpState.entity", @"Mass: %g", mass);
1030 : OOLog(@"dumpState.entity", @"Owner: %@", owner);
1031 :
1032 : flags = [NSMutableArray array];
1033 0 : #define ADD_FLAG_IF_SET(x) if (x) { [flags addObject:@#x]; }
1034 : ADD_FLAG_IF_SET(isShip);
1035 : ADD_FLAG_IF_SET(isStation);
1036 : ADD_FLAG_IF_SET(isPlayer);
1037 : ADD_FLAG_IF_SET(isWormhole);
1038 : ADD_FLAG_IF_SET(isSubEntity);
1039 : ADD_FLAG_IF_SET(hasMoved);
1040 : ADD_FLAG_IF_SET(hasRotated);
1041 : ADD_FLAG_IF_SET(isSunlit);
1042 : ADD_FLAG_IF_SET(throw_sparks);
1043 : flagsString = [flags count] ? [flags componentsJoinedByString:@", "] : (NSString *)@"none";
1044 : OOLog(@"dumpState.entity", @"Flags: %@", flagsString);
1045 : OOLog(@"dumpState.entity", @"Collision Test Filter: %u", collisionTestFilter);
1046 :
1047 : }
1048 :
1049 :
1050 0 : - (void)subEntityReallyDied:(ShipEntity *)sub
1051 : {
1052 : OOLog(@"entity.bug", @"%s called for non-ship entity %p by %p", __PRETTY_FUNCTION__, self, sub);
1053 : }
1054 :
1055 :
1056 : // For shader bindings.
1057 : - (GLfloat)universalTime
1058 : {
1059 : return [UNIVERSE getTime];
1060 : }
1061 :
1062 :
1063 : - (GLfloat)spawnTime
1064 : {
1065 : return spawnTime;
1066 : }
1067 :
1068 :
1069 : - (GLfloat)timeElapsedSinceSpawn
1070 : {
1071 : return [UNIVERSE getTime] - spawnTime;
1072 : }
1073 :
1074 :
1075 : - (void) setAtmosphereFogging: (OOColor *)fogging
1076 : {
1077 : [atmosphereFogging release];
1078 : atmosphereFogging = [fogging retain];
1079 : }
1080 :
1081 : - (OOColor *) fogUniform
1082 : {
1083 : return [[atmosphereFogging retain] autorelease];
1084 : }
1085 :
1086 : #ifndef NDEBUG
1087 : - (NSString *) descriptionForObjDumpBasic
1088 : {
1089 : NSString *result = [self descriptionComponents];
1090 : if (result != nil) result = [NSString stringWithFormat:@"%@ %@", NSStringFromClass([self class]), result];
1091 : else result = [self description];
1092 :
1093 : return result;
1094 : }
1095 :
1096 :
1097 : - (NSString *) descriptionForObjDump
1098 : {
1099 : NSString *result = [self descriptionForObjDumpBasic];
1100 :
1101 : result = [result stringByAppendingFormat:@" range: %g (visible: %@)", HPdistance([self position], [PLAYER position]), [self isVisible] ? @"yes" : @"no"];
1102 :
1103 : return result;
1104 : }
1105 :
1106 :
1107 : - (NSSet *) allTextures
1108 : {
1109 : return nil;
1110 : }
1111 : #endif
1112 :
1113 :
1114 : - (BOOL) isVisible
1115 : {
1116 : return cam_zero_distance <= ABSOLUTE_NO_DRAW_DISTANCE2;
1117 : }
1118 :
1119 :
1120 : - (BOOL) isInSpace
1121 : {
1122 : switch ([self status])
1123 : {
1124 : case STATUS_IN_FLIGHT:
1125 : case STATUS_DOCKING:
1126 : case STATUS_LAUNCHING:
1127 : case STATUS_AUTOPILOT_ENGAGED:
1128 : case STATUS_WITCHSPACE_COUNTDOWN:
1129 : case STATUS_BEING_SCOOPED:
1130 : case STATUS_EFFECT:
1131 : case STATUS_ACTIVE:
1132 : return YES;
1133 : default:
1134 : return NO;
1135 : }
1136 : }
1137 :
1138 :
1139 : - (BOOL) isImmuneToBreakPatternHide
1140 : {
1141 : return isImmuneToBreakPatternHide;
1142 : }
1143 :
1144 : @end
|