51static void DrawWormholeCorona(GLfloat inner_radius, GLfloat outer_radius,
int step, GLfloat z_distance, GLfloat *col4v1);
54@implementation WormholeEntity (Private)
58 if ((
self = [super
init]))
61 shipsInTransit = [[NSMutableArray arrayWithCapacity:4] retain];
62 collision_radius = 0.0;
64 scanClass = CLASS_WORMHOLE;
88 if ((
self = [
self init]))
90 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
94 origin = [dict oo_intForKey:@"origin_id" defaultValue:0];
95 destination = [dict oo_intForKey:@"dest_id" defaultValue:255];
97 originCoords = [[UNIVERSE systemManager] getCoordinatesForSystem:origin inGalaxy:[PLAYER galaxyNumber]];
98 destinationCoords = [[UNIVERSE systemManager] getCoordinatesForSystem:destination inGalaxy:[PLAYER galaxyNumber]];
106 expiry_time = [dict oo_doubleForKey:@"expiry_time"];
107 arrival_time = [dict oo_doubleForKey:@"arrival_time"];
109 if (expiry_time > arrival_time)
111 expiry_time = arrival_time - 1.0;
115 estimated_arrival_time = [dict oo_doubleForKey:@"estimated_arrival_time" defaultValue:arrival_time];
116 position = [dict oo_hpvectorForKey:@"position"];
117 _misjump = [dict oo_boolForKey:@"misjump" defaultValue:NO];
121 NSArray * shipDictsArray = [dict oo_arrayForKey:@"ships"];
122 NSEnumerator *shipDicts = [shipDictsArray objectEnumerator];
123 NSDictionary *currShipDict =
nil;
124 [shipsInTransit removeAllObjects];
125 NSMutableDictionary *restoreContext = [NSMutableDictionary dictionary];
127 while ((currShipDict = [shipDicts nextObject]) !=
nil)
129 NSDictionary *shipInfo = [currShipDict oo_dictionaryForKey:@"ship_info"];
137 [shipsInTransit addObject:[NSDictionary dictionaryWithObjectsAndKeys:
139 [currShipDict objectForKey:@"time_delta"], @"time",
144 OOLog(
@"wormhole.load.warning",
@"Wormhole ship \"%@\
" failed to initialize - missing OXP or old-style saved wormhole data.", [shipInfo oo_stringForKey:
@"ship_key"]);
157 if ((
self = [
self init]))
159 double now = [PLAYER clockTimeAdjusted];
164 origin = [UNIVERSE currentSystemID];
166 originCoords = [PLAYER galaxy_coordinates];
167 destinationCoords = [[UNIVERSE systemManager] getCoordinatesForSystem:destination inGalaxy:[PLAYER galaxyNumber]];
169 distance = fmax(distance, 0.1);
170 witch_mass = 200000.0;
172 witch_mass += [ship mass];
174 if (sun && ([sun willGoNova] || [sun goneNova]) && [ship mass] > 240000)
175 shrink_factor = [ship
mass] / 240000;
179 collision_radius = 0.5 *
M_PI * pow(witch_mass, 1.0/3.0);
181 travel_time = (distance * distance * 3600);
182 arrival_time = now + travel_time;
183 estimated_arrival_time = arrival_time;
190 if (expiry_time > arrival_time)
192 expiry_time = arrival_time - 1.0;
195 zero_distance = HPdistance2([
PLAYER position], position);
208 double time_adjust = distance * distance * (3600 - 2700);
209 arrival_time -= time_adjust;
210 travel_time -= time_adjust;
211 destinationCoords.x = (originCoords.x + destinationCoords.
x) / 2;
212 destinationCoords.y = (originCoords.y + destinationCoords.
y) / 2;
218- (void) setMisjumpWithRange:(GLfloat)range
220 if (range <= 0.0 || range >= 1.0)
224 _misjumpRange = range;
230 double time_adjust = (distance * (1-_misjumpRange))*(distance * (1-_misjumpRange))*3600.0;
233 arrival_time -= time_adjust;
234 travel_time -= time_adjust;
236 destinationCoords.x = (originCoords.x * (1-_misjumpRange)) + (destinationCoords.
x * _misjumpRange);
237 destinationCoords.y = (originCoords.y * (1-_misjumpRange)) + (destinationCoords.
y * _misjumpRange);
249- (GLfloat) misjumpRange
251 return _misjumpRange;
257 if (!ship || [ship status] == STATUS_ENTERING_WITCHSPACE)
266 if ([
PLAYER galaxy_coordinates].
x != originCoords.x || [
PLAYER galaxy_coordinates].y != originCoords.y)
271 double now = [PLAYER clockTimeAdjusted];
276 if( now > expiry_time )
281 float d = HPdistance(position, [ship position]);
282 d -= [ship collisionRadius] + [
self collisionRadius];
290 if (leader && (leader != ship))
293 float leaderShipSpeed = [leader
maxFlightSpeed] * afterburnerFactor;
294 if (leaderShipSpeed < shipSpeed ) shipSpeed = leaderShipSpeed;
296 if (shipSpeed <= 0.0f ) shipSpeed = 0.1f;
297 now += d / shipSpeed;
298 if( now > expiry_time )
304 [shipsInTransit addObject:[NSDictionary dictionaryWithObjectsAndKeys:
306 [NSNumber numberWithDouble: now + travel_time - arrival_time], @"time",
309 witch_mass += [ship mass];
312 if (expiry_time > arrival_time)
314 expiry_time = arrival_time - 1.0;
317 collision_radius = 0.5 *
M_PI * pow(witch_mass, 1.0/3.0);
319 [UNIVERSE addWitchspaceJumpEffectForShip:ship];
322 [ship
setStatus:STATUS_ENTERING_WITCHSPACE];
326 [UNIVERSE removeEntity:ship];
329 if ([ship isStation])
335 [UNIVERSE carryPlayerOn:(StationEntity*)ship inWormhole:self];
344- (void) disgorgeShips
346 double now = [PLAYER clockTimeAdjusted];
347 NSMutableArray* shipsStillInTransit = [[NSMutableArray alloc] initWithCapacity:[shipsInTransit count]];
348 BOOL hasShiftedExitPosition = NO;
349 BOOL useExitXYScatter = NO;
351 NSDictionary *shipInfo =
nil;
352 foreach (shipInfo, shipsInTransit)
354 ShipEntity *ship = [shipInfo objectForKey:@"ship"];
355 NSString *shipBeacon = [shipInfo objectForKey:@"shipBeacon"];
356 double ship_arrival_time = arrival_time + [shipInfo oo_doubleForKey:
@"time"];
357 double time_passed = now - ship_arrival_time;
359 if ([ship status] == STATUS_DEAD)
continue;
361 if (ship_arrival_time > now)
363 [shipsStillInTransit addObject:shipInfo];
368 if (!hasExitPosition)
370 position = [UNIVERSE getWitchspaceExitPosition];
371 GLfloat min_d1 = [UNIVERSE safeWitchspaceExitDistance];
382 if (fabs(d1) < min_d1)
384 d1 += ((d1 > 0.0)? min_d1: -min_d1);
386 position.x += v1.
x * d1;
387 position.y += v1.
y * d1;
388 position.z += v1.z * d1;
391 if (hasExitPosition && (!containsPlayer || useExitXYScatter))
399 double offset_x =
randf()*150.0-75.0;
400 double offset_y =
randf()*150.0-75.0;
401 shippos.x = position.x + (offset_x*exit_vector_x.
x)+(offset_y*exit_vector_y.
x);
402 shippos.y = position.y + (offset_x*exit_vector_x.
y)+(offset_y*exit_vector_y.
y);
403 shippos.z = position.z + (offset_x*exit_vector_x.z)+(offset_y*exit_vector_y.z);
409 [
self setExitSpeed:[ship
maxFlightSpeed]*WORMHOLE_LEADER_SPEED_FACTOR];
412 [PLAYER setSpeed:exit_speed];
414 useExitXYScatter = YES;
418 if (shipBeacon !=
nil)
433 if (time_passed < 2.0)
444 [UNIVERSE addEntity:ship];
456 if (!hasExitPosition)
458 hasExitPosition = YES;
459 hasShiftedExitPosition = YES;
460 [ship
update: time_passed];
463 else if (time_passed > 1)
465 if (hasShiftedExitPosition)
468 [ship
update: (ship_arrival_time - arrival_time)];
474 [ship
update:time_passed];
479 [shipsInTransit release];
480 shipsInTransit = shipsStillInTransit;
486 position = HPvector_add([
PLAYER position], vectorToHPVector(vector_multiply_scalar([
PLAYER forwardVector], -500.0f)));
494- (void) setContainsPlayer:(BOOL)val
496 containsPlayer = val;
500- (void) setExitPosition:(HPVector)pos
502 [
self setPosition: pos];
503 hasExitPosition = YES;
516- (NSPoint) originCoordinates
521- (NSPoint) destinationCoordinates
523 return destinationCoords;
532- (void) setExitSpeed:(
double) speed
543- (double) arrivalTime
737static void DrawWormholeCorona(GLfloat inner_radius, GLfloat outer_radius,
int step, GLfloat z_distance, GLfloat *col4v1)
739 if (outer_radius >= z_distance)
743 NSRange activity = { 0.34, 1.0 };
745 GLfloat s0, c0, s1, c1;
750 GLfloat theta, delta, halfStep;
752 r0 = outer_radius * z_distance / sqrt(z_distance * z_distance - outer_radius * outer_radius);
753 r1 = inner_radius * z_distance / sqrt(z_distance * z_distance - inner_radius * inner_radius);
755 delta = step *
M_PI / 180.0f;
756 halfStep = 0.5f * delta;
760 for (i = 0; i < 360; i += step )
767 q = activity.location + rv0 * activity.length;
769 s0 = r0 * sin(theta);
770 c0 = r0 * cos(theta);
771 glColor4f(col4v1[0] * q, col4v1[1] * q, col4v1[2] * q, col4v1[3] * rv0);
772 glVertex3f(s0, c0, 0.0);
774 s1 = r1 * sin(theta - halfStep) * 0.5 * (1.0 + rv1);
775 c1 = r1 * cos(theta - halfStep) * 0.5 * (1.0 + rv1);
776 glColor4f(col4v1[0], col4v1[1], col4v1[2], 0.0);
777 glVertex3f(s1, c1, 0.0);
784 q = activity.location + rv0 * activity.length;
788 glColor4f(col4v1[0] * q, col4v1[1] * q, col4v1[2] * q, col4v1[3] * rv0);
789 glVertex3f(s0, c0, 0.0);
791 s1 = r1 * sin(halfStep) * 0.5 * (1.0 + rv1);
792 c1 = r1 * cos(halfStep) * 0.5 * (1.0 + rv1);
793 glColor4f(col4v1[0], col4v1[1], col4v1[2], 0.0);
794 glVertex3f(s1, c1, 0.0);