27#import "MyOpenGLView.h"
97#if OO_LOCALIZATION_TOOLS
102#include <espeak/speak_lib.h>
112#define DEMO2_VANISHING_DISTANCE 650.0
113#define DEMO2_FLY_IN_STAGE_TIME 0.4
116#define MAX_NUMBER_OF_ENTITIES 200
117#define STANDARD_STATION_ROLL 0.4
119#define LANE_WIDTH 51200.0
130 1.0f, 1.0f, 1.0f, 1.0f,
131 1.0f, -1.0f, 1.0f, 0.0f,
132 -1.0f, -1.0f, 0.0f, 0.0f,
133 -1.0f, 1.0f, 0.0f, 1.0f
154#undef CACHE_ROUTE_FROM_SYSTEM_RESULTS
164+ (instancetype) elementWithLocation:(
OOSystemID) location parent:(
OOSystemID)parent cost:(
double) cost distance:(
double) distance time:(
double) time jumps:(
int) jumps;
176+ (instancetype) elementWithLocation:(
OOSystemID) location parent:(
OOSystemID) parent cost:(
double) cost distance:(
double) distance time:(
double) time jumps:(
int) jumps
187 return [r autorelease];
200@interface Universe (OOPrivate)
202- (void) initTargetFramebufferWithViewSize:(NSSize)viewSize;
204- (void) resizeTargetFramebufferWithViewSize:(NSSize)viewSize;
208- (BOOL) doRemoveEntity:(
Entity *)entity;
211- (HPVector) fractionalPositionFrom:(HPVector)point0 to:(HPVector)point1 withFraction:(
double)routeFraction;
215- (NSString *)chooseStringForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary;
217#if OO_LOCALIZATION_TOOLS
219- (void) dumpDebugGraphViz;
220- (void) dumpSystemDescriptionGraphViz;
222- (void) addNumericRefsInString:(NSString *)string toGraphViz:(NSMutableString *)graphViz fromNode:(NSString *)fromNode nodeCount:(NSUInteger)nodeCount;
232- (void) prunePreloadingPlanetMaterials;
238- (void) setFirstBeacon:(
Entity <OOBeaconEntity> *)beacon;
239- (void) setLastBeacon:(
Entity <OOBeaconEntity> *)beacon;
247- (Vector) randomPlaceWithinScannerFrom:(Vector)pos alongRoute:(Vector)route withOffset:(
double)offset;
266static GLfloat
sun_off[4] = {0.0, 0.0, 0.0, 1.0};
269#define DOCKED_AMBIENT_LEVEL 0.2f
270#define DOCKED_ILLUM_LEVEL 0.7f
277#define SUN_AMBIENT_INFLUENCE 0.75
279#define SKY_AMBIENT_ADJUSTMENT 0.0625
286- (void) setBloom: (BOOL)newBloom
293 return _currentPostFX;
296- (void) setCurrentPostFX: (
int) newCurrentPostFX
305 _colorblindMode = newCurrentPostFX;
308 _currentPostFX = newCurrentPostFX;
311- (
int) nextColorblindMode:(
int) index
319- (
int) prevColorblindMode:(
int) index
327- (
int) colorblindMode
329 return _colorblindMode;
332- (void) initTargetFramebufferWithViewSize:(NSSize)viewSize
335 OOGL(glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE));
336 OOGL(glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE));
337 OOGL(glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE));
340 OOGL(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &defaultDrawFBO));
342 GLint previousProgramID;
343 OOGL(glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgramID));
344 GLint previousTextureID;
345 OOGL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureID));
347 OOGL(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previousVAO));
348 GLint previousArrayBuffer;
349 OOGL(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousArrayBuffer));
350 GLint previousElementBuffer;
351 OOGL(glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &previousElementBuffer));
354 OOGL(glGenFramebuffers(1, &msaaFramebufferID));
355 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
358 OOGL(glGenTextures(1, &msaaTextureID));
359 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
360 OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, GL_TRUE));
361 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
362 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID, 0));
365 OOGL(glGenRenderbuffers(1, &msaaDepthBufferID));
366 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
367 OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
368 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
369 OOGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaaDepthBufferID));
371 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
373 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Multisample framebuffer not complete");
377 OOGL(glGenFramebuffers(1, &targetFramebufferID));
378 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
381 OOGL(glGenTextures(1, &targetTextureID));
382 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
383 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
384 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
385 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
388 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTextureID, 0));
391 OOGL(glGenRenderbuffers(1, &targetDepthBufferID));
392 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, targetDepthBufferID));
393 OOGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
394 OOGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, targetDepthBufferID));
396 GLenum attachment[1] = { GL_COLOR_ATTACHMENT0 };
397 OOGL(glDrawBuffers(1, attachment));
399 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
401 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Framebuffer not complete");
404 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
406 targetFramebufferSize = viewSize;
414 OOGL(glGenFramebuffers(1, &passthroughFramebufferID));
415 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, passthroughFramebufferID));
418 OOGL(glGenTextures(2, passthroughTextureID));
419 for (
unsigned int i = 0; i < 2; i++)
421 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[i]));
422 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
423 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
424 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
427 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, passthroughTextureID[i], 0));
430 GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
431 OOGL(glDrawBuffers(2, attachments));
433 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
435 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Passthrough framebuffer not complete");
437 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
440 OOGL(glGenFramebuffers(2, pingpongFBO));
441 OOGL(glGenTextures(2, pingpongColorbuffers));
442 for (
unsigned int i = 0; i < 2; i++)
444 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]));
445 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]));
446 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
447 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
448 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
451 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongColorbuffers[i], 0));
453 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
455 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Pingpong framebuffers not complete");
458 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
472 textureProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-texture.vertex"
473 fragmentShaderName:@"oolite-texture.fragment"
474 prefix:@"#version 330\n"
475 attributeBindings:[NSDictionary dictionary]] retain];
477 blurProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-blur.vertex"
478 fragmentShaderName:@"oolite-blur.fragment"
479 prefix:@"#version 330\n"
480 attributeBindings:[NSDictionary dictionary]] retain];
482 finalProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-final.vertex"
484 fragmentShaderName:[[UNIVERSE gameView] hdrOutput] ? @"oolite-final-hdr.fragment" : @"oolite-final.fragment"
486 fragmentShaderName:@"oolite-final.fragment"
488 prefix:@"#version 330\n"
489 attributeBindings:[NSDictionary dictionary]] retain];
492 OOGL(glGenVertexArrays(1, &quadTextureVAO));
493 OOGL(glGenBuffers(1, &quadTextureVBO));
494 OOGL(glGenBuffers(1, &quadTextureEBO));
496 OOGL(glBindVertexArray(quadTextureVAO));
498 OOGL(glBindBuffer(GL_ARRAY_BUFFER, quadTextureVBO));
501 OOGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadTextureEBO));
504 OOGL(glEnableVertexAttribArray(0));
506 OOGL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float), (
void*)0));
507 OOGL(glEnableVertexAttribArray(1));
509 OOGL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float), (
void*)(2 *
sizeof(
float))));
513 OOGL(glUseProgram(previousProgramID));
514 OOGL(glBindTexture(GL_TEXTURE_2D, previousTextureID));
515 OOGL(glBindVertexArray(previousVAO));
516 OOGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, previousElementBuffer));
517 OOGL(glBindBuffer(GL_ARRAY_BUFFER, previousArrayBuffer));
524 OOGL(glDeleteTextures(1, &msaaTextureID));
525 OOGL(glDeleteTextures(1, &targetTextureID));
526 OOGL(glDeleteTextures(2, passthroughTextureID));
527 OOGL(glDeleteTextures(2, pingpongColorbuffers));
528 OOGL(glDeleteRenderbuffers(1, &msaaDepthBufferID));
529 OOGL(glDeleteRenderbuffers(1, &targetDepthBufferID));
530 OOGL(glDeleteFramebuffers(1, &msaaFramebufferID));
531 OOGL(glDeleteFramebuffers(1, &targetFramebufferID));
532 OOGL(glDeleteFramebuffers(2, pingpongFBO));
533 OOGL(glDeleteFramebuffers(1, &passthroughFramebufferID));
534 OOGL(glDeleteVertexArrays(1, &quadTextureVAO));
535 OOGL(glDeleteBuffers(1, &quadTextureVBO));
536 OOGL(glDeleteBuffers(1, &quadTextureEBO));
537 [textureProgram release];
538 [blurProgram release];
539 [finalProgram release];
543- (void) resizeTargetFramebufferWithViewSize:(NSSize)viewSize
547 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
548 OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, GL_TRUE));
549 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
552 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
553 OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
554 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
557 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
558 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
559 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
561 for (i = 0; i < 2; i++)
563 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]));
564 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
565 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
568 for (i = 0; i < 2; i++)
570 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[i]));
571 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
572 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
576 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, targetDepthBufferID));
577 OOGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
578 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
580 targetFramebufferSize.width = viewSize.width;
581 targetFramebufferSize.height = viewSize.height;
589 OOGL(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previousFBO));
590 GLint previousProgramID;
591 OOGL(glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgramID));
592 GLint previousTextureID;
593 OOGL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureID));
595 OOGL(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previousVAO));
596 GLint previousActiveTexture;
597 OOGL(glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture));
599 OOGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
601 OOGL(glDisable(GL_BLEND));
603 GLhandleARB program = [textureProgram program];
604 GLhandleARB blur = [blurProgram program];
605 GLhandleARB
final = [finalProgram program];
606 NSSize viewSize = [gameView viewSize];
607 float fboResolution[2] = {viewSize.width, viewSize.height};
609 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, passthroughFramebufferID));
610 OOGL(glClear(GL_COLOR_BUFFER_BIT));
612 OOGL(glUseProgram(program));
613 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
614 OOGL(glUniform1i(glGetUniformLocation(program,
"image"), 0));
617 OOGL(glBindVertexArray(quadTextureVAO));
618 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
619 OOGL(glBindVertexArray(0));
621 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
624 BOOL horizontal = YES, firstIteration = YES;
625 unsigned int amount = [
self bloom] ? 10 : 0;
626 OOGL(glUseProgram(blur));
627 for (
unsigned int i = 0; i < amount; i++)
629 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]));
630 OOGL(glUniform1i(glGetUniformLocation(blur,
"horizontal"), horizontal));
631 OOGL(glActiveTexture(GL_TEXTURE0));
633 OOGL(glBindTexture(GL_TEXTURE_2D, firstIteration ? passthroughTextureID[1] : pingpongColorbuffers[!horizontal]));
634 OOGL(glUniform1i(glGetUniformLocation([blurProgram program],
"imageIn"), 0));
635 OOGL(glBindVertexArray(quadTextureVAO));
636 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
637 OOGL(glBindVertexArray(0));
638 horizontal = !horizontal;
641 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
644 OOGL(glUseProgram(
final));
646 OOGL(glActiveTexture(GL_TEXTURE0));
647 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[0]));
648 OOGL(glUniform1i(glGetUniformLocation(
final,
"scene"), 0));
649 OOGL(glUniform1i(glGetUniformLocation(
final,
"bloom"), [
self bloom]));
650 OOGL(glUniform1f(glGetUniformLocation(
final,
"uTime"), [
self getTime]));
651 OOGL(glUniform2fv(glGetUniformLocation(
final,
"uResolution"), 1, fboResolution));
652 OOGL(glUniform1i(glGetUniformLocation(
final,
"uPostFX"), [
self currentPostFX]));
654 if([gameView hdrOutput])
656 OOGL(glUniform1f(glGetUniformLocation(
final,
"uMaxBrightness"), [gameView hdrMaxBrightness]));
657 OOGL(glUniform1f(glGetUniformLocation(
final,
"uPaperWhiteBrightness"), [gameView hdrPaperWhiteBrightness]));
661 OOGL(glActiveTexture(GL_TEXTURE1));
662 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]));
663 OOGL(glUniform1i(glGetUniformLocation(
final,
"bloomBlur"), 1));
664 OOGL(glUniform1f(glGetUniformLocation(
final,
"uSaturation"), [gameView colorSaturation]));
666 OOGL(glBindVertexArray(quadTextureVAO));
667 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
671 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
674 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, previousFBO));
675 OOGL(glActiveTexture(previousActiveTexture));
676 OOGL(glBindTexture(GL_TEXTURE_2D, previousTextureID));
677 OOGL(glUseProgram(previousProgramID));
678 OOGL(glBindVertexArray(previousVAO));
679 OOGL(glEnable(GL_BLEND));
687 [NSException raise:NSInternalInconsistencyException format:@"%s: expected only one Universe to exist at a time.", __PRETTY_FUNCTION__];
693 if (
self ==
nil)
return nil;
699 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
703 useAddOns = [[NSString alloc] initWithString:SCENARIO_OXP_DEFINITION_ALL];
705 [
self setGameView:inGameView];
708 allPlanets = [[NSMutableArray alloc] init];
709 allStations = [[NSMutableSet alloc] init];
716 [
self setDetailLevelDirectly:[prefs oo_intForKey:@"detailLevel"
719 [
self initTargetFramebufferWithViewSize:[gameView viewSize]];
726#if OOLITE_SPEECH_SYNTH
727 OOLog(
@"speech.synthesis",
@"Spoken messages are %@.", ([prefs oo_boolForKey:
@"speech_on" defaultValue:NO] ?
@"on" :
@"off"));
734 [
self loadDescriptions];
738 [
self loadScenarios];
740 autoSave = [prefs oo_boolForKey:@"autosave" defaultValue:NO];
741 wireframeGraphics = [prefs oo_boolForKey:@"wireframe-graphics" defaultValue:NO];
742 doProcedurallyTexturedPlanets = [prefs oo_boolForKey:@"procedurally-textured-planets" defaultValue:YES];
743 [inGameView
setGammaValue:[prefs oo_floatForKey:@"gamma-value" defaultValue:1.0f]];
744 [inGameView
setMsaa:[prefs oo_boolForKey:@"anti-aliasing" defaultValue:NO]];
745 OOLog(
@"MSAA.setup",
@"Multisample anti-aliasing %@requested.", [inGameView msaa] ?
@"" :
@"not ");
746 [inGameView
setFov:OOClamp_0_max_f([prefs oo_floatForKey:@"fov-value" defaultValue:57.2f], MAX_FOV_DEG)
fromFraction:NO];
750#if OOLITE_SPEECH_SYNTH
752 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
762 OOLog(
@"speech.setup.begin",
@"Starting to set up speech synthesizer.");
763 NSSpeechSynthesizer *synth = [[NSSpeechSynthesizer alloc] init];
764 OOLog(
@"speech.setup.end",
@"Finished setting up speech synthesizer.");
765 speechSynthesizer = synth;
769 espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 100, NULL, 0);
770 espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_NONE, 0);
771 espeak_SetParameter(espeakVOLUME, volume, 0);
772 espeak_voices = espeak_ListVoices(NULL);
773 for (espeak_voice_count = 0;
774 espeak_voices[espeak_voice_count];
775 ++espeak_voice_count)
785 entities = [[NSMutableArray arrayWithCapacity:MAX_NUMBER_OF_ENTITIES] retain];
795 waypoints = [[NSMutableDictionary alloc] init];
797 [
self setUpSettings];
808 [
self setUpCargoPods];
812 [
self addEntity:player];
817 [
self setUpInitialUniverse];
820 entitiesDeadThisUpdate = [[NSMutableSet alloc] init];
821 framesDoneThisUpdate = 0;
830 [
self populateNormalSpace];
834#if OO_LOCALIZATION_TOOLS
835 [
self runLocalizationTools];
837 [
self dumpDebugGraphViz];
852 [currentMessage release];
855 [message_gui release];
856 [comm_log_gui release];
860 [commodities release];
862 [_descriptions release];
863 [characters release];
864 [customSounds release];
865 [globalSettings release];
866 [systemManager release];
867 [missiontext release];
868 [equipmentData release];
869 [equipmentDataOutfitting release];
870 [demo_ships release];
872 [screenBackgrounds release];
874 [populatorSettings release];
875 [system_repopulator release];
876 [allPlanets release];
877 [allStations release];
878 [explosionSettings release];
880 [activeWormholes release];
881 [characterPool release];
882 [universeRegion release];
890 for (i = 0; i < 256; i++) [system_names[i] release];
892 [entitiesDeadThisUpdate release];
896#if OOLITE_SPEECH_SYNTH
897 [speechArray release];
899 [speechSynthesizer release];
904 [conditionScripts release];
906 [
self deleteOpenGLObjects];
912- (NSUInteger) sessionID
920 return _doingStartUp;
924- (BOOL) doProcedurallyTexturedPlanets
926 return doProcedurallyTexturedPlanets;
930- (void) setDoProcedurallyTexturedPlanets:(BOOL) value
932 doProcedurallyTexturedPlanets = !!value;
933 [[NSUserDefaults standardUserDefaults] setBool:doProcedurallyTexturedPlanets forKey:@"procedurally-textured-planets"];
937- (NSString *) useAddOns
943- (BOOL) setUseAddOns:(NSString *) newUse fromSaveGame:(BOOL) saveGame
945 return [
self setUseAddOns:newUse fromSaveGame:saveGame forceReinit:NO];
949- (BOOL) setUseAddOns:(NSString *) newUse fromSaveGame:(BOOL) saveGame forceReinit:(BOOL)force
951 if (!force && [newUse isEqualToString:useAddOns])
956 useAddOns = [newUse retain];
958 return [
self reinitAndShowDemo:!saveGame];
963- (NSUInteger) entityCount
965 return [entities count];
970- (void) debugDumpEntities
973 int show_count = n_entities;
977 OOLog(
@"universe.objectDump",
@"DEBUG: Entity Dump - [entities count] = %lu,\tn_entities = %u", [entities
count], n_entities);
980 for (i = 0; i < show_count; i++)
982 OOLog(
@"universe.objectDump",
@"Ent:%4u %@", i, [sortedEntities[i] descriptionForObjDump]);
986 if ([entities
count] != n_entities)
988 OOLog(
@"universe.objectDump",
@"entities = %@", [entities description]);
993- (NSArray *) entityList
995 return [NSArray arrayWithArray:entities];
1005 [
self setPauseMessageVisible:NO];
1006 NSString *pauseKey = [PLAYER keyBindingDescription2:@"key_pausebutton"];
1008 if ([player status] == STATUS_DOCKED)
1010 if ([gui setForegroundTextureKey:
@"paused_docked_overlay"])
1012 [gui drawGUI:1.0 drawCursor:NO];
1016 [
self setPauseMessageVisible:YES];
1017 [
self addMessage:OOExpandKey(@"game-paused-docked", pauseKey) forCount:1.0];
1022 if ([player guiScreen] != GUI_SCREEN_MAIN && [gui setForegroundTextureKey:
@"paused_overlay"])
1024 [gui drawGUI:1.0 drawCursor:NO];
1028 [
self setPauseMessageVisible:YES];
1029 [
self addMessage:OOExpandKey(@"game-paused", pauseKey) forCount:1.0];
1033 [[
self gameController] setGamePaused:YES];
1047 ShipScriptEvent(context, player,
"shipWillEnterWitchspace", STRING_TO_JSVAL(JS_InternString(context, [[player jumpCause] UTF8String])), INT_TO_JSVAL(dest));
1050 [
self allShipsDoScriptEvent:OOJSID("playerWillEnterWitchspace") andReactToAIMessage:@"PLAYER WITCHSPACE"];
1057 [
self removeAllEntitiesExceptPlayer];
1062 if (![wormhole withMisjump])
1065 [
self setSystemTo: dest];
1068 [
self populateNormalSpace];
1076 [
self setUpWitchspaceBetweenSystem:[wormhole
origin] andSystem:[wormhole
destination]];
1085 [UNIVERSE setSkyColorRed:0.0f
1090 [
self setWitchspaceBreakPattern:YES];
1098- (void) setUpUniverseFromStation
1108 OOSystemID sys = [
self findSystemNumberAtCoords:coords withGalaxy:[player
galaxyNumber] includingHidden:YES];
1113 if (dockedStation && !interstel)
1117 [
self setSystemTo: sys];
1119 while ([entities
count] > 2)
1121 Entity *ent = [entities objectAtIndex:index];
1122 if ((ent != player)&&(ent != dockedStation))
1126 [
self removeEntity:ent];
1136 if (dockedStation ==
nil) [
self removeAllEntitiesExceptPlayer];
1139 if (!dockedStation || !interstel)
1142 [
self populateNormalSpace];
1145 if ([dockedStation maxFlightSpeed] > 0)
1147 float d1 = [
self randomDistanceWithinScanner];
1148 HPVector pos = [UNIVERSE getWitchspaceExitPosition];
1152 if (abs((
int)d1) < 2750)
1154 d1 += ((d1 > 0.0)? 2750.0f: -2750.0f);
1163 [
self setWitchspaceBreakPattern:YES];
1171 if(!autoSaveNow) [
self setViewDirection:VIEW_FORWARD];
1175 [UNIVERSE setSkyColorRed:0.0f
1182- (void) setUpUniverseFromWitchspace
1189 if ([entities
count] == 0)
1194 [
self addEntity:player];
1200 player = [PLAYER retain];
1204 [
self populateNormalSpace];
1209 [
self setViewDirection:VIEW_FORWARD];
1211 [comm_log_gui printLongText:[NSString stringWithFormat:@"%@ %@", [
self getSystemName:systemID], [player
dial_clock_adjusted]]
1218- (void) setUpUniverseFromMisjump
1225 if ([entities
count] == 0)
1230 [
self addEntity:player];
1236 player = [PLAYER retain];
1239 [
self setUpWitchspace];
1242 [
self setAirResistanceFactor:0.0f];
1247 [
self setViewDirection:VIEW_FORWARD];
1253- (void) setUpWitchspace
1255 [
self setUpWitchspaceBetweenSystem:[PLAYER systemID] andSystem:[PLAYER nextHopTargetSystemID]];
1267 NSString* override_key = [
self keyForInterstellarOverridesForSystems:s1 :s2 inGalaxy:galaxyID];
1269 NSDictionary *systeminfo = [systemManager getPropertiesForSystemKey:override_key];
1271 [universeRegion clearSubregions];
1278 thing = [[
SkyEntity alloc] initWithColors:col1:col2 andSystemInfo: systeminfo];
1282 [
self addEntity:thing];
1288 [
self addEntity:thing];
1291 ambientLightLevel = [systeminfo oo_floatForKey:@"ambient_level" defaultValue:1.0];
1297 [
self clearSystemPopulator];
1298 NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:@"interstellarSpaceWillPopulate"];
1299 [system_repopulator release];
1300 system_repopulator = [[systeminfo oo_stringForKey:@"repopulator" defaultValue:@"interstellarSpaceWillRepopulate"] retain];
1302 [PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
1304 [
self populateSystemFromDictionariesWithSun:nil andPlanet:nil];
1307 NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
1308 if (script_actions !=
nil)
1310 OOStandardsDeprecated([NSString stringWithFormat:
@"The script_actions system info key is deprecated for %@.",override_key]);
1326- (OOPlanetEntity *) setUpPlanet
1329 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1332 NSMutableDictionary *planetDict = [NSMutableDictionary dictionaryWithDictionary:[systemManager getPropertiesForCurrentSystem]];
1333 [planetDict oo_setBool:YES forKey:@"mainForLocalSystem"];
1334 OOPlanetEntity *a_planet = [[OOPlanetEntity alloc] initFromDictionary:planetDict withAtmosphere:[planetDict oo_boolForKey:@"has_atmosphere" defaultValue:YES] andSeed:systemSeed forSystem:systemID];
1336 double planet_zpos = [planetDict oo_floatForKey:@"planet_distance" defaultValue:500000];
1337 planet_zpos *= [planetDict oo_floatForKey:@"planet_distance_multiplier" defaultValue:1.0];
1339#ifdef OO_DUMP_PLANETINFO
1340 OOLog(
@"planetinfo.record",
@"planet zpos = %f",planet_zpos);
1342 [a_planet setPosition:(HPVector){ 0, 0, planet_zpos }];
1343 [a_planet setEnergy:1000000.0];
1345 if ([allPlanets
count]>0)
1347 OOPlanetEntity *tmp=[allPlanets objectAtIndex:0];
1348 [
self addEntity:a_planet];
1349 [allPlanets removeObject:a_planet];
1350 cachedPlanet=a_planet;
1351 [allPlanets replaceObjectAtIndex:0 withObject:a_planet];
1352 [
self removeEntity:(Entity *)tmp];
1356 [
self addEntity:a_planet];
1358 return [a_planet autorelease];
1370 OOPlanetEntity *a_planet;
1372 HPVector stationPos;
1377 NSDictionary *systeminfo = [systemManager getPropertiesForCurrentSystem];
1378 unsigned techlevel = [systeminfo oo_unsignedIntForKey:KEY_TECHLEVEL];
1379 NSString *stationDesc =
nil, *defaultStationDesc =
nil;
1384 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1388 sunGoneNova = [systeminfo oo_boolForKey:@"sun_gone_nova" defaultValue:NO];
1391 [universeRegion clearSubregions];
1394 [
self setSkyColorRed:0.0f
1400#ifdef OO_DUMP_PLANETINFO
1401 OOLog(
@"planetinfo.record",
@"seed = %d %d %d %d",system_seed.c,system_seed.d,system_seed.e,system_seed.f);
1402 OOLog(
@"planetinfo.record",
@"coordinates = %d %d",system_seed.d,system_seed.b);
1404#define SPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = \"%@\";",[systeminfo oo_stringForKey:@"" #PROP]);
1405#define IPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %d;",[systeminfo oo_intForKey:@#PROP]);
1406#define FPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %f;",[systeminfo oo_floatForKey:@"" #PROP]);
1411 IPROP(productivity);
1424 float h2 = h1 + 1.0 / (1.0 + (
Ranrot() % 5));
1430 thing = [[
SkyEntity alloc] initWithColors:col1:col2 andSystemInfo: systeminfo];
1432 [
self addEntity:thing];
1441 ambientLightLevel = [systeminfo oo_floatForKey:@"ambient_level" defaultValue:1.0];
1445 dict_object=[systeminfo objectForKey:@"sun_color"];
1446 if (dict_object!=
nil)
1462 [
self addEntity:thing];
1467 float defaultSunFlare =
randf()*0.1;
1468 float defaultSunHues = 0.5+
randf()*0.5;
1474 a_planet=[
self setUpPlanet];
1475 double planet_radius = [a_planet radius];
1484 double sun_distance;
1485 double sunDistanceModifier;
1486 double safeDistance;
1489 sunDistanceModifier = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_modifier" defaultValue:0.0];
1490 if (sunDistanceModifier < 6.0)
1492 sun_distance = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance" defaultValue:(planet_radius*20)];
1494 sun_distance *= [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_multiplier" defaultValue:1];
1498 sun_distance = planet_radius * sunDistanceModifier;
1501 sun_radius = [systeminfo oo_nonNegativeDoubleForKey:@"sun_radius" defaultValue:2.5 * planet_radius];
1503 if ((sun_radius < 1000.0) || (sun_radius > sun_distance / 2 && !sunGoneNova))
1505 OOLogWARN(
@"universe.setup.badSun",
@"Sun radius of %f is not valid for this system",sun_radius);
1506 sun_radius = sun_radius < 1000.0 ? 1000.0 : (sun_distance / 2);
1508#ifdef OO_DUMP_PLANETINFO
1509 OOLog(
@"planetinfo.record",
@"sun_radius = %f",sun_radius);
1511 safeDistance=36 * sun_radius * sun_radius;
1515 HPVector sun_dir = [systeminfo oo_hpvectorForKey:@"sun_vector"];
1516 sun_distance /= 2.0;
1519 sun_distance *= 2.0;
1520 sunPos = HPvector_subtract([a_planet position],
1521 HPvector_multiply_scalar(sun_dir,sun_distance));
1525 while (HPmagnitude2(sunPos) < safeDistance);
1529 [a_planet setOrientation:quaternion_rotation_betweenHP(sun_dir,make_HPvector(1.0,0.0,0.0))];
1531#ifdef OO_DUMP_PLANETINFO
1532 OOLog(
@"planetinfo.record",
@"sun_vector = %.3f %.3f %.3f",vf.x,vf.y,vf.z);
1533 OOLog(
@"planetinfo.record",
@"sun_distance = %.0f",sun_distance);
1538 NSMutableDictionary *sun_dict = [NSMutableDictionary dictionaryWithCapacity:5];
1539 [sun_dict setObject:[NSNumber numberWithDouble:sun_radius] forKey:@"sun_radius"];
1540 dict_object=[systeminfo objectForKey: @"corona_shimmer"];
1541 if (dict_object!=
nil) [sun_dict setObject:dict_object forKey:@"corona_shimmer"];
1542 dict_object=[systeminfo objectForKey: @"corona_hues"];
1543 if (dict_object!=
nil)
1545 [sun_dict setObject:dict_object forKey:@"corona_hues"];
1549 [sun_dict setObject:[NSNumber numberWithFloat:defaultSunHues] forKey:@"corona_hues"];
1551 dict_object=[systeminfo objectForKey: @"corona_flare"];
1552 if (dict_object!=
nil)
1554 [sun_dict setObject:dict_object forKey:@"corona_flare"];
1558 [sun_dict setObject:[NSNumber numberWithFloat:defaultSunFlare] forKey:@"corona_flare"];
1560 dict_object=[systeminfo objectForKey:KEY_SUNNAME];
1561 if (dict_object!=
nil)
1563 [sun_dict setObject:dict_object forKey:KEY_SUNNAME];
1565#ifdef OO_DUMP_PLANETINFO
1566 OOLog(
@"planetinfo.record",
@"corona_flare = %f",[sun_dict oo_floatForKey:
@"corona_flare"]);
1567 OOLog(
@"planetinfo.record",
@"corona_hues = %f",[sun_dict oo_floatForKey:
@"corona_hues"]);
1568 OOLog(
@"planetinfo.record",
@"sun_color = %@",[bgcolor descriptionComponents]);
1570 a_sun = [[
OOSunEntity alloc] initSunWithColor:bgcolor andDictionary:sun_dict];
1575 [
self addEntity:a_sun];
1590 stationPos = [a_planet position];
1592 vf = [systeminfo oo_vectorForKey:@"station_vector"];
1593#ifdef OO_DUMP_PLANETINFO
1594 OOLog(
@"planetinfo.record",
@"station_vector = %.3f %.3f %.3f",vf.x,vf.y,vf.z);
1596 stationPos = HPvector_subtract(stationPos, vectorToHPVector(vector_multiply_scalar(vf, 2.0 * planet_radius)));
1600 stationDesc = [systeminfo oo_stringForKey:@"station" defaultValue:@"coriolis"];
1601#ifdef OO_DUMP_PLANETINFO
1602 OOLog(
@"planetinfo.record",
@"station = %@",stationDesc);
1605 a_station = (
StationEntity *)[
self newShipWithRole:stationDesc];
1617 if (![a_station isStation] || ![a_station validForAddToUniverse])
1619 if (a_station ==
nil)
1622 OOLog(
@"universe.setup.badStation",
@"Failed to set up a ship for role \"%@\
" as system station, trying again with \"%@\".", stationDesc, defaultStationDesc);
1626 OOLog(
@"universe.setup.badStation",
@"***** ERROR: Attempt to use non-station ship of type \"%@\
" for role \"%@\" as system station, trying again with \"%@\".", [a_station name], stationDesc, defaultStationDesc);
1628 [a_station release];
1629 stationDesc = defaultStationDesc;
1630 a_station = (
StationEntity *)[
self newShipWithRole:stationDesc];
1632 if (![a_station isStation] || ![a_station validForAddToUniverse])
1634 if (a_station ==
nil)
1636 OOLog(
@"universe.setup.badStation",
@"On retry, failed to set up a ship for role \"%@\
" as system station. Trying to fall back to built-in Coriolis station.", stationDesc);
1640 OOLog(
@"universe.setup.badStation",
@"***** ERROR: On retry, rolled non-station ship of type \"%@\
" for role \"%@\". Non-station ships should not have this role! Trying to fall back to built-in Coriolis station.", [a_station name], stationDesc);
1642 [a_station release];
1644 a_station = (
StationEntity *)[
self newShipWithName:
@"coriolis-station"];
1645 if (![a_station isStation] || ![a_station validForAddToUniverse])
1647 OOLog(
@"universe.setup.badStation",
@"%@",
@"Could not create built-in Coriolis station! Generating a stationless system.");
1653 if (a_station !=
nil)
1655 [a_station
setOrientation:quaternion_rotation_between(vf,make_vector(0.0,0.0,1.0))];
1661 [
self addEntity:a_station];
1669 cachedPlanet = a_planet;
1670 cachedStation = a_station;
1676 [
self populateSpaceFromActiveWormholes];
1680 [a_station release];
1684- (void) populateNormalSpace
1686 NSDictionary *systeminfo = [systemManager getPropertiesForCurrentSystem];
1688 BOOL sunGoneNova = [systeminfo oo_boolForKey:@"sun_gone_nova"];
1694 HPVector v0 = make_HPvector(0,0,34567.89);
1695 double min_safe_dist2 = 6000000.0 * 6000000.0;
1696 HPVector sunPos = [cachedSun position];
1697 while (HPmagnitude2(cachedSun->position) < min_safe_dist2)
1701 sunPos = HPvector_add(sunPos, v0);
1702 [cachedSun setPosition:sunPos];
1706 [
self removeEntity:cachedPlanet];
1708 [
self removeEntity:cachedStation];
1709 cachedStation =
nil;
1714 [
self clearSystemPopulator];
1716 if ([
PLAYER status] != STATUS_START_GAME)
1718 NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:(sunGoneNova)?@"novaSystemWillPopulate":@"systemWillPopulate"];
1719 [system_repopulator release];
1720 system_repopulator = [[systeminfo oo_stringForKey:@"repopulator" defaultValue:(sunGoneNova)?@"novaSystemWillRepopulate":@"systemWillRepopulate"] retain];
1723 [PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
1725 [
self populateSystemFromDictionariesWithSun:cachedSun andPlanet:cachedPlanet];
1731 NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
1732 if (script_actions !=
nil)
1734 OOStandardsDeprecated([NSString stringWithFormat:
@"The script_actions system info key is deprecated for %@.",[
self getSystemName:systemID]]);
1738 [PLAYER runUnsanitizedScriptActions:script_actions
1739 allowingAIMethods:NO
1740 withContextName:@"<system script_actions>"
1750- (void) clearSystemPopulator
1752 [populatorSettings release];
1753 populatorSettings = [[NSMutableDictionary alloc] initWithCapacity:128];
1757- (NSDictionary *) getPopulatorSettings
1759 return populatorSettings;
1763- (void) setPopulatorSetting:(NSString *)key to:(NSDictionary *)setting
1767 [populatorSettings removeObjectForKey:key];
1771 [populatorSettings setObject:setting forKey:key];
1776- (BOOL) deterministicPopulation
1778 return deterministic_population;
1782- (void) populateSystemFromDictionariesWithSun:(
OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet
1784 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1785 NSArray *blocks = [populatorSettings allValues];
1786 NSEnumerator *enumerator = [[blocks sortedArrayUsingFunction:populatorPrioritySort context:nil] objectEnumerator];
1787 NSDictionary *populator =
nil;
1789 uint32_t i, locationSeed, groupCount, rndvalue;
1792 NSString *locationCode =
nil;
1794 while ((populator = [enumerator nextObject]))
1796 deterministic_population = [populator oo_boolForKey:@"deterministic" defaultValue:NO];
1800 deterministic_population = NO;
1803 locationSeed = [populator oo_unsignedIntForKey:@"locationSeed" defaultValue:0];
1804 groupCount = [populator oo_unsignedIntForKey:@"groupCount" defaultValue:1];
1806 for (i = 0; i < groupCount; i++)
1808 locationCode = [populator oo_stringForKey:@"location" defaultValue:@"COORDINATES"];
1809 if ([locationCode isEqualToString:
@"COORDINATES"])
1811 location = [populator oo_hpvectorForKey:@"coordinates" defaultValue:kZeroHPVector];
1815 if (locationSeed != 0)
1831 deterministic_population = NO;
1833 if (sun ==
nil || planet ==
nil)
1836 location = [
self locationByCode:@"WITCHPOINT" withSun:nil andPlanet:nil];
1840 location = [
self locationByCode:locationCode withSun:sun andPlanet:planet];
1842 if(locationSeed != 0)
1849 pdef = [populator objectForKey:@"callbackObj"];
1854 deterministic_population = NO;
1872- (HPVector) locationByCode:(NSString *)code withSun:(
OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet
1875 if ([code isEqualToString:
@"WITCHPOINT"] || sun ==
nil || planet ==
nil || [sun goneNova])
1882 if ([code isEqualToString:
@"LANE_WPS"])
1885 double l1 = HPmagnitude([planet position]);
1886 double l2 = HPmagnitude(HPvector_subtract([sun position],[planet position]));
1887 double l3 = HPmagnitude([sun position]);
1888 double total = l1+l2+l3;
1889 float choice =
randf();
1890 if (choice < l1/total)
1892 return [
self locationByCode:@"LANE_WP" withSun:sun andPlanet:planet];
1894 else if (choice < (l1+l2)/total)
1896 return [
self locationByCode:@"LANE_PS" withSun:sun andPlanet:planet];
1900 return [
self locationByCode:@"LANE_WS" withSun:sun andPlanet:planet];
1903 else if ([code isEqualToString:
@"LANE_WP"])
1907 else if ([code isEqualToString:
@"LANE_WS"])
1911 else if ([code isEqualToString:
@"LANE_PS"])
1915 else if ([code isEqualToString:
@"STATION_AEGIS"])
1920 }
while(HPdistance2(result,[planet position])<[planet radius]*[planet radius]*1.5);
1923 else if ([code isEqualToString:
@"PLANET_ORBIT_LOW"])
1927 else if ([code isEqualToString:
@"PLANET_ORBIT"])
1931 else if ([code isEqualToString:
@"PLANET_ORBIT_HIGH"])
1935 else if ([code isEqualToString:
@"STAR_ORBIT_LOW"])
1939 else if ([code isEqualToString:
@"STAR_ORBIT"])
1943 else if ([code isEqualToString:
@"STAR_ORBIT_HIGH"])
1947 else if ([code isEqualToString:
@"TRIANGLE"])
1960 result = HPvector_add(HPvector_multiply_scalar([planet position],r),HPvector_multiply_scalar([sun position],s));
1963 while(HPdistance2(result,[sun position]) < [sun radius]*[sun radius]*9.0 || HPdistance2(result,[planet position]) < [planet radius]*[planet radius]*9.0 || HPmagnitude2(result) <
SCANNER_MAX_RANGE2 * 9.0);
1965 else if ([code isEqualToString:
@"INNER_SYSTEM"])
1968 result =
OORandomPositionInShell([sun position],[sun radius]*3.0,HPdistance([sun position],[planet position]));
1972 }
while (HPdistance2(result,[sun position]) < [sun radius]*[sun radius]*9.0);
1974 else if ([code isEqualToString:
@"INNER_SYSTEM_OFFPLANE"])
1976 result =
OORandomPositionInShell([sun position],[sun radius]*3.0,HPdistance([sun position],[planet position]));
1978 else if ([code isEqualToString:
@"OUTER_SYSTEM"])
1980 result =
OORandomPositionInShell([sun position],HPdistance([sun position],[planet position]),HPdistance([sun position],[planet position])*10.0);
1984 else if ([code isEqualToString:
@"OUTER_SYSTEM_OFFPLANE"])
1986 result =
OORandomPositionInShell([sun position],HPdistance([sun position],[planet position]),HPdistance([sun position],[planet position])*10.0);
1998- (void) setAmbientLightLevel:(
float)newValue
2000 NSAssert(
UNIVERSE !=
nil,
@"Attempt to set ambient light level with a non yet existent universe.");
2002 ambientLightLevel = OOClamp_0_max_f(newValue, 10.0f);
2007- (float) ambientLightLevel
2009 return ambientLightLevel;
2033 GLfloat sun_pos[] = {0.0, 0.0, 0.0, 1.0};
2034 GLfloat sun_ambient[] = {0.0, 0.0, 0.0, 1.0};
2037 for (i = n_entities - 1; i > 0; i--)
2038 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[SkyEntity class]]))
2039 the_sky = (
SkyEntity*)sortedEntities[i];
2045 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
2046 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
2047 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
2055 stars_ambient[0] = 0.05; stars_ambient[1] = 0.20; stars_ambient[2] = 0.05; stars_ambient[3] = 1.0;
2056 sun_diffuse[0] = 0.85; sun_diffuse[1] = 1.0; sun_diffuse[2] = 0.85; sun_diffuse[3] = 1.0;
2057 sun_specular[0] = 0.95; sun_specular[1] = 1.0; sun_specular[2] = 0.95; sun_specular[3] = 1.0;
2058 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
2059 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
2060 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
2063 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, sun_pos));
2069 [[the_sky skyColor] getRed:&r green:&g blue:&b alpha:&a];
2073 GLfloat ambient_level = [
self ambientLightLevel];
2077 stars_ambient[3] = 1.0;
2085 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
2090- (void) forceLightSwitch
2096- (void) setMainLightPosition: (Vector) sunPos
2098 main_light_position[0] = sunPos.x;
2099 main_light_position[1] = sunPos.y;
2100 main_light_position[2] = sunPos.z;
2101 main_light_position[3] = 1.0;
2105- (
ShipEntity *) addShipWithRole:(NSString *)desc launchPos:(HPVector)launchPos rfactor:(GLfloat)rfactor
2110 launchPos.x += 2 * rfactor * (
randf() - 0.5);
2111 launchPos.y += 2 * rfactor * (
randf() - 0.5);
2112 launchPos.z += 2 * rfactor * (
randf() - 0.5);
2115 ShipEntity *ship = [
self newShipWithRole:desc];
2122 if ([ship hasRole:
@"cargopod"]) [
self fillCargopodWithRandomCargo:ship];
2125 if (![ship crew] && ![ship isUnpiloted])
2126 [ship
setCrew:[NSArray arrayWithObject:
2130 if ([ship scanClass] == CLASS_NOT_SET)
2134 [
self addEntity:ship];
2142- (void) addShipWithRole:(NSString *) desc nearRouteOneAt:(
double) route_fraction
2146 Entity *theStation = [
self station];
2152 HPVector launchPos = OOHPVectorInterpolate([
self getWitchspaceExitPosition], [theStation position], route_fraction);
2154 [
self addShipWithRole:desc launchPos:launchPos rfactor:SCANNER_MAX_RANGE];
2158- (HPVector) coordinatesForPosition:(HPVector) pos withCoordinateSystem:(NSString *) system returningScalar:(GLfloat*) my_scalar
2195 NSString* l_sys = [system lowercaseString];
2196 if ([l_sys length] != 3)
2198 OOPlanetEntity* the_planet = [
self planet];
2200 if (the_planet ==
nil || the_sun ==
nil || [l_sys isEqualToString:
@"abs"])
2202 if (my_scalar) *my_scalar = 1.0;
2205 HPVector w_pos = [
self getWitchspaceExitPosition];
2206 HPVector p_pos = the_planet->
position;
2207 HPVector s_pos = the_sun->
position;
2209 const char* c_sys = [l_sys UTF8String];
2210 HPVector p0, p1, p2;
2219 p1 = p_pos; p2 = s_pos;
break;
2221 p1 = s_pos; p2 = p_pos;
break;
2231 p1 = w_pos; p2 = s_pos;
break;
2233 p1 = s_pos; p2 = w_pos;
break;
2243 p1 = w_pos; p2 = p_pos;
break;
2245 p1 = p_pos; p2 = w_pos;
break;
2253 HPVector k = HPvector_normal_or_zbasis(HPvector_subtract(p1, p0));
2254 HPVector v = HPvector_normal_or_xbasis(HPvector_subtract(p2, p0));
2256 HPVector j = HPcross_product(k, v);
2257 HPVector i = HPcross_product(j, k);
2259 GLfloat scale = 1.0;
2263 scale = [the_planet radius];
2267 scale = [the_sun
radius];
2271 scale = HPmagnitude(HPvector_subtract(p1, p0));
2285 HPVector result = p0;
2286 result.x += scale * (pos.
x * i.
x + pos.
y * j.
x + pos.z * k.
x);
2287 result.y += scale * (pos.
x * i.
y + pos.
y * j.
y + pos.z * k.
y);
2288 result.z += scale * (pos.
x * i.z + pos.
y * j.z + pos.z * k.z);
2294- (NSString *) expressPosition:(HPVector) pos inCoordinateSystem:(NSString *) system
2296 HPVector result = [
self legacyPositionFrom:pos asCoordinateSystem:system];
2297 return [NSString stringWithFormat:@"%@ %.2f %.2f %.2f", system, result.x, result.y, result.z];
2301- (HPVector) legacyPositionFrom:(HPVector) pos asCoordinateSystem:(NSString *) system
2303 NSString* l_sys = [system lowercaseString];
2304 if ([l_sys length] != 3)
2306 OOPlanetEntity* the_planet = [
self planet];
2308 if (the_planet ==
nil || the_sun ==
nil || [l_sys isEqualToString:
@"abs"])
2312 HPVector w_pos = [
self getWitchspaceExitPosition];
2313 HPVector p_pos = the_planet->
position;
2314 HPVector s_pos = the_sun->
position;
2316 const char* c_sys = [l_sys UTF8String];
2317 HPVector p0, p1, p2;
2326 p1 = p_pos; p2 = s_pos;
break;
2328 p1 = s_pos; p2 = p_pos;
break;
2338 p1 = w_pos; p2 = s_pos;
break;
2340 p1 = s_pos; p2 = w_pos;
break;
2350 p1 = w_pos; p2 = p_pos;
break;
2352 p1 = p_pos; p2 = w_pos;
break;
2360 HPVector k = HPvector_normal_or_zbasis(HPvector_subtract(p1, p0));
2361 HPVector v = HPvector_normal_or_xbasis(HPvector_subtract(p2, p0));
2363 HPVector j = HPcross_product(k, v);
2364 HPVector i = HPcross_product(j, k);
2366 GLfloat scale = 1.0;
2371 scale = 1.0f / [the_planet radius];
2376 scale = 1.0f / [the_sun
radius];
2381 scale = 1.0f / HPdistance(p1, p0);
2393 HPVector r_pos = HPvector_subtract(pos, p0);
2394 HPVector result = make_HPvector(scale * (r_pos.x * i.x + r_pos.y * i.y + r_pos.z * i.z),
2395 scale * (r_pos.x * j.x + r_pos.y * j.y + r_pos.z * j.z),
2396 scale * (r_pos.x * k.x + r_pos.y * k.y + r_pos.z * k.z) );
2402- (HPVector) coordinatesFromCoordinateSystemString:(NSString *) system_x_y_z
2405 if ([tokens
count] != 4)
2408 return make_HPvector(0,0,0);
2411 return [
self coordinatesForPosition:make_HPvector([tokens oo_floatAtIndex:1], [tokens oo_floatAtIndex:2], [tokens oo_floatAtIndex:3]) withCoordinateSystem:[tokens oo_stringAtIndex:0] returningScalar:&dummy];
2415- (BOOL) addShipWithRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2418 GLfloat scalar = 1.0;
2419 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2421 GLfloat rfactor = scalar;
2427 return ([
self addShipWithRole:desc launchPos:launchPos rfactor:rfactor] !=
nil);
2431- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc atPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2434 GLfloat scalar = 1.0;
2435 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2436 GLfloat distance_from_center = 0.0;
2437 HPVector v_from_center, ship_pos;
2438 HPVector ship_positions[howMany];
2440 int scale_up_after = 0;
2441 int current_shell = 0;
2442 GLfloat walk_factor = 2.0;
2445 ShipEntity *ship = [
self addShipWithRole:desc launchPos:launchPos rfactor:0.0];
2446 if (ship ==
nil)
return NO;
2452 int limit_count = 8;
2459 v_from_center.x += walk_factor * (
randf() - 0.5);
2460 v_from_center.y += walk_factor * (
randf() - 0.5);
2461 v_from_center.z += walk_factor * (
randf() - 0.5);
2462 }
while ((v_from_center.x == 0.0)&&(v_from_center.y == 0.0)&&(v_from_center.z == 0.0));
2463 v_from_center = HPvector_normal(v_from_center);
2465 ship_pos = make_HPvector( launchPos.x + distance_from_center * v_from_center.x,
2466 launchPos.y + distance_from_center * v_from_center.y,
2467 launchPos.z + distance_from_center * v_from_center.z);
2472 while (safe && (j >= current_shell))
2474 safe = (safe && (HPdistance2(ship_pos, ship_positions[j]) > safe_distance2));
2483 distance_from_center += sqrt(safe_distance2);
2490 [ship setScanClass:scanClass == CLASS_NOT_SET ? CLASS_NEUTRAL : scanClass];
2498 ship_positions[i] = ship_pos;
2500 if (i > scale_up_after)
2503 scale_up_after += 1 + 2 * i;
2504 distance_from_center += sqrt(safe_distance2);
2511- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2514 GLfloat scalar = 1.0;
2515 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2516 GLfloat rfactor = scalar;
2521 BoundingBox launch_bbox;
2522 bounding_box_reset_to_vector(&launch_bbox, make_vector(launchPos.x - rfactor, launchPos.y - rfactor, launchPos.z - rfactor));
2523 bounding_box_add_xyz(&launch_bbox, launchPos.x + rfactor, launchPos.y + rfactor, launchPos.z + rfactor);
2525 return [
self addShips: howMany withRole: desc intoBoundingBox: launch_bbox];
2529- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system withinRadius:(GLfloat) radius
2532 GLfloat scalar = 1.0;
2533 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2534 GLfloat rfactor = radius;
2537 BoundingBox launch_bbox;
2538 bounding_box_reset_to_vector(&launch_bbox, make_vector(launchPos.x - rfactor, launchPos.y - rfactor, launchPos.z - rfactor));
2539 bounding_box_add_xyz(&launch_bbox, launchPos.x + rfactor, launchPos.y + rfactor, launchPos.z + rfactor);
2541 return [
self addShips: howMany withRole: desc intoBoundingBox: launch_bbox];
2545- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc intoBoundingBox:(BoundingBox) bbox
2552 int h0 = howMany / 2;
2553 int h1 = howMany - h0;
2555 GLfloat lx = bbox.max.x - bbox.min.
x;
2556 GLfloat ly = bbox.max.y - bbox.min.
y;
2557 GLfloat lz = bbox.max.z - bbox.min.z;
2558 BoundingBox bbox0 = bbox;
2559 BoundingBox bbox1 = bbox;
2560 if ((lx > lz)&&(lx > ly))
2562 bbox0.min.x += 0.5 * lx;
2563 bbox1.max.x -= 0.5 * lx;
2569 bbox0.min.y += 0.5 * ly;
2570 bbox1.max.y -= 0.5 * ly;
2574 bbox0.min.z += 0.5 * lz;
2575 bbox1.max.z -= 0.5 * lz;
2579 return ([
self addShips: h0 withRole: desc intoBoundingBox: bbox0] && [
self addShips: h1 withRole: desc intoBoundingBox: bbox1]);
2583 HPVector pos = make_HPvector(bbox.min.x, bbox.min.y, bbox.min.z);
2584 pos.x += 0.5 * (
randf() +
randf()) * (bbox.max.
x - bbox.min.
x);
2585 pos.y += 0.5 * (
randf() +
randf()) * (bbox.max.
y - bbox.min.
y);
2586 pos.z += 0.5 * (
randf() +
randf()) * (bbox.max.z - bbox.min.z);
2588 return ([
self addShipWithRole:desc launchPos:pos rfactor:0.0] !=
nil);
2592- (BOOL) spawnShip:(NSString *) shipdesc
2596 OOStandardsDeprecated([NSString stringWithFormat:
@"'spawn' via legacy script is deprecated as a way of adding ships for %@",shipdesc]);
2599 NSDictionary *shipdict =
nil;
2602 if (shipdict ==
nil)
return NO;
2604 ship = [
self newShipWithName:shipdesc];
2606 if (ship ==
nil)
return NO;
2609 NSDictionary *spawndict = [shipdict oo_dictionaryForKey:@"spawn"];
2610 HPVector pos, rpos, spos;
2611 NSString *positionString =
nil;
2614 positionString = [spawndict oo_stringForKey:@"position"];
2615 if (positionString !=
nil)
2617 if([positionString hasPrefix:
@"abs "] && ([
self planet] !=
nil || [
self sun] !=
nil))
2619 OOLogWARN(
@"script.deprecated",
@"setting %@ for %@ '%@' in 'abs' inside .plists can cause compatibility issues across Oolite versions. Use coordinates relative to main system objects instead.",
@"position",
@"entity",shipdesc);
2622 pos = [
self coordinatesFromCoordinateSystemString:positionString];
2628 OOLogERR(
@"universe.spawnShip.error",
@"***** ERROR: failed to find a spawn position for ship %@.", shipdesc);
2633 positionString = [spawndict oo_stringForKey:@"facing_position"];
2634 if (positionString !=
nil)
2636 if([positionString hasPrefix:
@"abs "] && ([
self planet] !=
nil || [
self sun] !=
nil))
2638 OOLogWARN(
@"script.deprecated",
@"setting %@ for %@ '%@' in 'abs' inside .plists can cause compatibility issues across Oolite versions. Use coordinates relative to main system objects instead.",
@"facing_position",
@"entity",shipdesc);
2643 rpos = [
self coordinatesFromCoordinateSystemString:positionString];
2644 rpos = HPvector_subtract(rpos, spos);
2648 rpos = HPvector_normal(rpos);
2657 q1 = make_quaternion(0,1,0,0);
2665 [
self addEntity:ship];
2672- (void) witchspaceShipWithPrimaryRole:(NSString *)role
2676 NSDictionary *systeminfo =
nil;
2679 systeminfo = [
self currentSystemData];
2680 government = [systeminfo oo_unsignedCharForKey:KEY_GOVERNMENT];
2682 ship = [
self newShipWithRole:role];
2685 if (ship && [ship hasRole:
@"cargopod"])
2687 [
self fillCargopodWithRandomCargo:ship];
2692 if (([ship scanClass] == CLASS_NO_DRAW)||([ship scanClass] == CLASS_NOT_SET))
2694 if ([role isEqual:
@"trader"])
2697 if ([ship hasRole:
@"sunskim-trader"] &&
randf() < 0.25)
2700 [
self makeSunSkimmer:ship andSetAI:YES];
2707 if (([ship pendingEscortCount] > 0)&&((
Ranrot() % 7) < government))
2710 [ship setPendingEscortCount:(nx > 0) ? nx : 0];
2713 if ([role isEqual:
@"pirate"])
2716 [ship
setBounty: (Ranrot() & 7) + (Ranrot() & 7) + ((randf() < 0.05)? 63 : 23)
withReason:kOOLegalStatusReasonSetup];
2718 if ([ship crew] ==
nil && ![ship isUnpiloted])
2719 [ship
setCrew:[NSArray arrayWithObject:
2732 if (entity ==
nil)
return nil;
2742 ship = [
self addShipWithRole:desc launchPos:spawn_pos rfactor:0.0];
2759 [vis setPosition:pos];
2760 [vis setOrientation:OORandomQuaternion()];
2762 success = [
self addEntity:vis];
2772- (
ShipEntity *) addShipAt:(HPVector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius
2777 if (radius == NSNotFound)
2779 GLfloat scalar = 1.0;
2780 [
self coordinatesForPosition:pos withCoordinateSystem:@"abs" returningScalar:&scalar];
2782 GLfloat rfactor = scalar;
2796 ShipEntity *ship = [
self newShipWithRole:role];
2802 if ([ship hasRole:
@"cargopod"]) [
self fillCargopodWithRandomCargo:ship];
2804 if (scanClass == CLASS_NOT_SET)
2806 scanClass = CLASS_NEUTRAL;
2810 if ([ship crew] ==
nil && ![ship isUnpiloted])
2812 [ship
setCrew:[NSArray arrayWithObject:
2819 BOOL trader = [role isEqualToString:@"trader"];
2829 if (pendingEscortCount > 0)
2831 OOGovernmentID government = [[
self currentSystemData] oo_unsignedCharForKey:KEY_GOVERNMENT];
2832 if ((
Ranrot() % 7) < government)
2834 int nx = pendingEscortCount - 2 * (1 + (
Ranrot() & 3));
2835 [ship setPendingEscortCount:(nx > 0) ? nx : 0];
2843 success = [
self addEntity:ship];
2850 if ([ship hasRole:
@"sunskim-trader"] &&
randf() < 0.25)
2853 [
self makeSunSkimmer:ship andSetAI:YES];
2860 else if ([role isEqual:
@"pirate"])
2862 [ship
setBounty:(Ranrot() & 7) + (Ranrot() & 7) + ((randf() < 0.05)? 63 : 23)
withReason:kOOLegalStatusReasonSetup];
2879- (NSArray *) addShipsAt:(HPVector)pos withRole:(NSString *)role quantity:(
unsigned)count withinRadius:(GLfloat)radius asGroup:(BOOL)isGroup
2883 NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
2894 ship = [
self addShipAt:pos withRole:role withinRadius:radius];
2898 if (isGroup) [ship
setGroup:group];
2899 [ships addObject:ship];
2903 if ([ships
count] == 0)
return nil;
2905 return [[ships copy] autorelease];
2911- (NSArray *) addShipsToRoute:(NSString *)route withRole:(NSString *)role quantity:(
unsigned)count routeFraction:(
double)routeFraction asGroup:(BOOL)isGroup
2913 NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
2919 if ([route isEqualToString:
@"pw"] || [route isEqualToString:
@"sw"] || [route isEqualToString:
@"ps"])
2921 routeFraction = 1.0f - routeFraction;
2925 if ([route isEqualTo:
@"wp"] || [route isEqualTo:
@"pw"])
2927 point0 = [
self getWitchspaceExitPosition];
2928 entity = [
self planet];
2929 if (entity ==
nil)
return nil;
2931 radius = [entity radius];
2933 else if ([route isEqualTo:
@"ws"] || [route isEqualTo:
@"sw"])
2935 point0 = [
self getWitchspaceExitPosition];
2936 entity = [
self sun];
2937 if (entity ==
nil)
return nil;
2939 radius = [entity radius];
2941 else if ([route isEqualTo:
@"sp"] || [route isEqualTo:
@"ps"])
2943 entity = [
self sun];
2944 if (entity ==
nil)
return nil;
2946 double radius0 = [entity radius];
2948 entity = [
self planet];
2949 if (entity ==
nil)
return nil;
2951 radius = [entity radius];
2954 direction = HPvector_normal(HPvector_subtract(point0, point1));
2955 point0 = HPvector_subtract(point0, HPvector_multiply_scalar(direction, radius0 +
SCANNER_MAX_RANGE * 1.1f));
2957 else if ([route isEqualTo:
@"st"])
2959 point0 = [
self getWitchspaceExitPosition];
2960 if ([
self station] ==
nil)
return nil;
2961 point1 = [[
self station] position];
2962 radius = [[
self station] collisionRadius];
2967 direction = HPvector_normal(HPvector_subtract(point1, point0));
2968 point1 = HPvector_subtract(point1, HPvector_multiply_scalar(direction, radius +
SCANNER_MAX_RANGE * 1.1f));
2970 pos = [
self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
2973 return [
self addShipsAt:pos withRole:role quantity:count withinRadius:(SCANNER_MAX_RANGE / 10.0f) asGroup:YES];
2979 ship = [
self addShipAt:pos withRole:role withinRadius:0];
2980 if (ship !=
nil) [ships addObject:ship];
2981 if (
count > 0) pos = [
self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
2984 if ([ships
count] == 0)
return nil;
2987 return [[ships copy] autorelease];
2991- (BOOL) roleIsPirateVictim:(NSString *)role
2993 return [
self role:role isInCategory:@"oolite-pirate-victim"];
2997- (BOOL) role:(NSString *)role isInCategory:(NSString *)category
2999 NSSet *categoryInfo = [roleCategories objectForKey:category];
3000 if (categoryInfo ==
nil)
3004 return [categoryInfo containsObject:role];
3009- (void) forceWitchspaceEntries
3012 for (i = 0; i < n_entities; i++)
3014 if (sortedEntities[i]->isShip)
3018 if ([my_target isWormhole])
3022 else if ([[[my_ship getAI] state] isEqualToString:
@"ENTER_WORMHOLE"])
3031- (void) addWitchspaceJumpEffectForShip:(
ShipEntity *)ship
3034 if ([
PLAYER status] != STATUS_ENTERING_WITCHSPACE && [
PLAYER status] != STATUS_EXITING_WITCHSPACE)
3042- (GLfloat) safeWitchspaceExitDistance
3044 for (
unsigned i = 0; i < n_entities; i++)
3046 Entity *e2 = sortedEntities[i];
3047 if ([e2 isShip] && [(
ShipEntity*)e2 hasPrimaryRole:
@"buoy-witchpoint"])
3056- (void) setUpBreakPattern:(HPVector) pos orientation:(Quaternion) q forDocking:(BOOL) forDocking
3063 [
self setViewDirection:VIEW_FORWARD];
3075 colorDesc = [[
self globalSettings] objectForKey:@"hyperspace_tunnel_color_1"];
3076 if (colorDesc !=
nil)
3079 if (color !=
nil) col1 = color;
3080 else OOLogWARN(
@"hyperspaceTunnel.fromDict",
@"could not interpret \"%@\
" as a colour.", colorDesc);
3083 colorDesc = [[
self globalSettings] objectForKey:@"hyperspace_tunnel_color_2"];
3084 if (colorDesc !=
nil)
3087 if (color !=
nil) col2 = color;
3088 else OOLogWARN(
@"hyperspaceTunnel.fromDict",
@"could not interpret \"%@\
" as a colour.", colorDesc);
3092 GLfloat startAngle = 0;
3093 GLfloat aspectRatio = 1;
3097 NSDictionary *info = [[PLAYER dockedStation] shipInfoDictionary];
3098 sides = [info oo_unsignedIntForKey:@"tunnel_corners" defaultValue:4];
3099 startAngle = [info oo_floatForKey:@"tunnel_start_angle" defaultValue:45.0f];
3100 aspectRatio = [info oo_floatForKey:@"tunnel_aspect_ratio" defaultValue:2.67f];
3103 for (i = 1; i < 11; i++)
3112 [ring
setPosition:HPvector_add(pos, vectorToHPVector(offset))];
3115 [ring
setLifetime:i * BREAK_PATTERN_RING_SPACING];
3119 if (forDocking && ![[
PLAYER dockedStation] hasBreakPattern])
3123 else if (!forDocking && ![
self witchspaceBreakPattern])
3127 [
self addEntity:ring];
3128 breakPatternCounter++;
3133- (BOOL) witchspaceBreakPattern
3135 return _witchspaceBreakPattern;
3139- (void) setWitchspaceBreakPattern:(BOOL)newValue
3141 _witchspaceBreakPattern = !!newValue;
3145- (BOOL) dockingClearanceProtocolActive
3147 return _dockingClearanceProtocolActive;
3151- (void) setDockingClearanceProtocolActive:(BOOL)newValue
3154 NSEnumerator *statEnum = [allStations objectEnumerator];
3162 while ((station = [statEnum nextObject]))
3165 if (![[[registry shipInfoForKey:stationKey] allKeys] containsObject:
@"requires_docking_clearance"])
3171 _dockingClearanceProtocolActive = !!newValue;
3175- (void) handleGameOver
3177 if ([[
self gameController] playerFileToLoad])
3179 [[
self gameController] loadPlayerIfRequired];
3183 [
self setUseAddOns:SCENARIO_OXP_DEFINITION_ALL fromSaveGame:NO forceReinit:YES];
3188- (void) setupIntroFirstGo:(BOOL)justCobra
3192 Quaternion q2 = { 0.0f, 0.0f, 1.0f, 0.0f };
3200 [
self removeDemoShips];
3212 ship = [
self newShipWithName:PLAYER_SHIP_DESC usePlayerProxy:YES];
3218 demo_ship_index = 0;
3219 demo_ship_subindex = 0;
3223 NSArray *subList =
nil;
3224 foreach (subList, demo_ships)
3226 if ([[[subList oo_dictionaryAtIndex:0] oo_stringForKey:
kOODemoShipClass] isEqualToString:
@"ship"])
3228 demo_ship_index = [demo_ships indexOfObject:subList];
3229 NSDictionary *shipEntry =
nil;
3230 foreach (shipEntry, subList)
3232 if ([[shipEntry oo_stringForKey:
kOODemoShipKey] isEqualToString:
@"cobra3-trader"])
3234 demo_ship_subindex = [subList indexOfObject:shipEntry];
3243 if (!demo_ship) ship = [
self newShipWithName:[[[demo_ships oo_arrayAtIndex:demo_ship_index] oo_dictionaryAtIndex:demo_ship_subindex] oo_stringForKey:kOODemoShipKey] usePlayerProxy:NO];
3254 [ship
setPositionX:0.0f
y:0.0f
z:DEMO2_VANISHING_DISTANCE * ship->collision_radius * 0.01];
3267 [
self addEntity:ship];
3269 [ship
setStatus:STATUS_COCKPIT_DISPLAY];
3278 [
self setLibraryTextForDemoShip];
3281 [
self enterGUIViewModeWithMouseInteraction:NO];
3285 demo_stage_time = universal_time + 300.0;
3292 return [[demo_ships oo_arrayAtIndex:demo_ship_index] oo_dictionaryAtIndex:demo_ship_subindex];
3302 [gui setTabStops:tab_stops];
3307 NSDictionary *librarySettings = [
self demoShipData];
3311 NSString *field1 =
nil;
3312 NSString *field2 =
nil;
3313 NSString *field3 =
nil;
3314 NSString *
override =
nil;
3317 for (NSUInteger i=1;i<=26;i++)
3319 [gui setText:@"" forRow:i];
3323 override = [librarySettings oo_stringForKey:kOODemoShipClass defaultValue:@"ship"];
3327 field2 = [demo_ship shipClassName];
3330 override = [librarySettings oo_stringForKey:kOODemoShipSummary defaultValue:nil];
3331 if (
override !=
nil)
3339 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:1];
3351 override = [librarySettings oo_stringForKey:kOODemoShipSpeed defaultValue:nil];
3352 if (
override !=
nil)
3354 if ([
override length] == 0)
3360 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-speed-custom"),OOExpand(override)];
3369 override = [librarySettings oo_stringForKey:kOODemoShipTurnRate defaultValue:nil];
3370 if (
override !=
nil)
3372 if ([
override length] == 0)
3378 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-turn-custom"),OOExpand(override)];
3387 override = [librarySettings oo_stringForKey:kOODemoShipCargo defaultValue:nil];
3388 if (
override !=
nil)
3390 if ([
override length] == 0)
3396 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-cargo-custom"),OOExpand(override)];
3405 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:3];
3408 override = [librarySettings oo_stringForKey:kOODemoShipGenerator defaultValue:nil];
3409 if (
override !=
nil)
3411 if ([
override length] == 0)
3417 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-generator-custom"),OOExpand(override)];
3426 override = [librarySettings oo_stringForKey:kOODemoShipShields defaultValue:nil];
3427 if (
override !=
nil)
3429 if ([
override length] == 0)
3435 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-shields-custom"),OOExpand(override)];
3444 override = [librarySettings oo_stringForKey:kOODemoShipWitchspace defaultValue:nil];
3445 if (
override !=
nil)
3447 if ([
override length] == 0)
3453 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-witchspace-custom"),OOExpand(override)];
3462 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:4];
3466 override = [librarySettings oo_stringForKey:kOODemoShipWeapons defaultValue:nil];
3467 if (
override !=
nil)
3469 if ([
override length] == 0)
3475 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-weapons-custom"),OOExpand(override)];
3483 override = [librarySettings oo_stringForKey:kOODemoShipTurrets defaultValue:nil];
3484 if (
override !=
nil)
3486 if ([
override length] == 0)
3492 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-turrets-custom"),OOExpand(override)];
3500 override = [librarySettings oo_stringForKey:kOODemoShipSize defaultValue:nil];
3501 if (
override !=
nil)
3503 if ([
override length] == 0)
3509 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-size-custom"),OOExpand(override)];
3517 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:5];
3520 override = [librarySettings oo_stringForKey:kOODemoShipDescription defaultValue:nil];
3521 if (
override !=
nil)
3523 [gui addLongText:OOExpand(override) startingAtRow:descRow align:GUI_ALIGN_LEFT];
3528 field1 = [NSString stringWithFormat:@"<-- %@",OOShipLibraryCategoryPlural([[[demo_ships objectAtIndex:((demo_ship_index+[demo_ships count]-1)%[demo_ships count])] objectAtIndex:0] oo_stringForKey:kOODemoShipClass])];
3530 field3 = [NSString stringWithFormat:@"%@ -->",OOShipLibraryCategoryPlural([[[demo_ships objectAtIndex:((demo_ship_index+1)%[demo_ships count])] objectAtIndex:0] oo_stringForKey:kOODemoShipClass])];
3532 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:19];
3536 NSArray *subList = [demo_ships objectAtIndex:demo_ship_index];
3537 NSUInteger i,start = demo_ship_subindex - (demo_ship_subindex%5);
3538 NSUInteger end = start + 4;
3539 if (end >= [subList
count])
3541 end = [subList count] - 1;
3546 for (i = start ; i <= end ; i++)
3548 field2 = [[subList objectAtIndex:i] oo_stringForKey:kOODemoShipName];
3549 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:row];
3550 if (i == demo_ship_subindex)
3564 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:20];
3567 if (end < [subList
count]-1)
3569 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:26];
3576- (void) selectIntro2Previous
3579 NSUInteger subcount = [[demo_ships objectAtIndex:demo_ship_index] count];
3580 demo_ship_subindex = (demo_ship_subindex + subcount - 2) % subcount;
3581 demo_stage_time = universal_time - 1.0;
3585- (void) selectIntro2PreviousCategory
3588 demo_ship_index = (demo_ship_index + [demo_ships
count] - 1) % [demo_ships
count];
3589 demo_ship_subindex = [[demo_ships objectAtIndex:demo_ship_index] count] - 1;
3590 demo_stage_time = universal_time - 1.0;
3594- (void) selectIntro2NextCategory
3597 demo_ship_index = (demo_ship_index + 1) % [demo_ships
count];
3598 demo_ship_subindex = [[demo_ships objectAtIndex:demo_ship_index] count] - 1;
3599 demo_stage_time = universal_time - 1.0;
3603- (void) selectIntro2Next
3606 demo_stage_time = universal_time - 1.0;
3616static BOOL IsFriendlyStationPredicate(
Entity *entity,
void *parameter)
3624 if (cachedSun !=
nil && cachedStation ==
nil)
3626 cachedStation = [
self findOneEntityMatchingPredicate:IsCandidateMainStationPredicate
3629 return cachedStation;
3633- (
StationEntity *) stationWithRole:(NSString *)role andPosition:(HPVector)position
3635 if ([role isEqualToString:
@""])
3640 float range = 1000000;
3642 NSArray *stations = [
self stations];
3644 foreach (station, stations)
3646 if (HPdistance2(position,[station position]) < range)
3648 if ([[station primaryRole] isEqualToString:role])
3662 return [
self findOneEntityMatchingPredicate:IsFriendlyStationPredicate parameter:ship];
3666- (OOPlanetEntity *) planet
3668 if (cachedPlanet ==
nil && [allPlanets
count] > 0)
3670 cachedPlanet = [allPlanets objectAtIndex:0];
3672 return cachedPlanet;
3678 if (cachedSun ==
nil)
3680 cachedSun = [
self findOneEntityMatchingPredicate:IsSunPredicate parameter:nil];
3686- (NSArray *) planets
3692- (NSArray *) stations
3694 return [allStations allObjects];
3698- (NSArray *) wormholes
3700 return activeWormholes;
3704- (void) unMagicMainStation
3716 if (playerStatus == STATUS_START_GAME)
return;
3720 cachedStation =
nil;
3724- (void) resetBeacons
3726 Entity <OOBeaconEntity> *beaconShip = [
self firstBeacon], *next =
nil;
3729 next = [beaconShip nextBeacon];
3730 [beaconShip setPrevBeacon:nil];
3731 [beaconShip setNextBeacon:nil];
3735 [
self setFirstBeacon:nil];
3736 [
self setLastBeacon:nil];
3740- (
Entity <OOBeaconEntity> *) firstBeacon
3742 return [_firstBeacon weakRefUnderlyingObject];
3746- (void) setFirstBeacon:(
Entity <OOBeaconEntity> *)beacon
3748 if (beacon != [
self firstBeacon])
3750 [beacon setPrevBeacon:nil];
3751 [beacon setNextBeacon:[
self firstBeacon]];
3752 [[
self firstBeacon] setPrevBeacon:beacon];
3753 [_firstBeacon release];
3754 _firstBeacon = [beacon weakRetain];
3759- (
Entity <OOBeaconEntity> *) lastBeacon
3761 return [_lastBeacon weakRefUnderlyingObject];
3765- (void) setLastBeacon:(
Entity <OOBeaconEntity> *)beacon
3767 if (beacon != [
self lastBeacon])
3769 [beacon setNextBeacon:nil];
3770 [beacon setPrevBeacon:[
self lastBeacon]];
3771 [[
self lastBeacon] setNextBeacon:beacon];
3772 [_lastBeacon release];
3773 _lastBeacon = [beacon weakRetain];
3778- (void) setNextBeacon:(
Entity <OOBeaconEntity> *) beaconShip
3780 if ([beaconShip isBeacon])
3782 [
self setLastBeacon:beaconShip];
3783 if ([
self firstBeacon] ==
nil) [
self setFirstBeacon:beaconShip];
3787 OOLog(
@"universe.beacon.error",
@"***** ERROR: Universe setNextBeacon '%@'. The ship has no beacon code set.", beaconShip);
3792- (void) clearBeacon:(
Entity <OOBeaconEntity> *) beaconShip
3794 Entity <OOBeaconEntity> *tmp =
nil;
3796 if ([beaconShip isBeacon])
3798 if ([
self firstBeacon] == beaconShip)
3800 tmp = [[beaconShip nextBeacon] nextBeacon];
3801 [
self setFirstBeacon:[beaconShip nextBeacon]];
3802 [[beaconShip prevBeacon] setNextBeacon:tmp];
3804 else if ([
self lastBeacon] == beaconShip)
3806 tmp = [[beaconShip prevBeacon] prevBeacon];
3807 [
self setLastBeacon:[beaconShip prevBeacon]];
3808 [[beaconShip nextBeacon] setPrevBeacon:tmp];
3812 [[beaconShip nextBeacon] setPrevBeacon:[beaconShip prevBeacon]];
3813 [[beaconShip prevBeacon] setNextBeacon:[beaconShip nextBeacon]];
3815 [beaconShip setBeaconCode:nil];
3820- (NSDictionary *) currentWaypoints
3826- (void) defineWaypoint:(NSDictionary *)definition forKey:(NSString *)key
3829 BOOL preserveCompass = NO;
3830 waypoint = [waypoints objectForKey:key];
3831 if (waypoint !=
nil)
3833 if ([
PLAYER compassTarget] == waypoint)
3835 preserveCompass = YES;
3837 [
self removeEntity:waypoint];
3838 [waypoints removeObjectForKey:key];
3840 if (definition !=
nil)
3843 if (waypoint !=
nil)
3845 [
self addEntity:waypoint];
3846 [waypoints setObject:waypoint forKey:key];
3847 if (preserveCompass)
3849 [PLAYER setCompassTarget:waypoint];
3850 [PLAYER setNextBeacon:waypoint];
3857- (GLfloat *) skyClearColor
3859 return skyClearColor;
3863- (void) setSkyColorRed:(GLfloat)red green:(GLfloat)green blue:(GLfloat)blue alpha:(GLfloat)alpha
3865 skyClearColor[0] = red;
3866 skyClearColor[1] = green;
3867 skyClearColor[2] = blue;
3868 skyClearColor[3] = alpha;
3869 [
self setAirResistanceFactor:alpha];
3873- (BOOL) breakPatternOver
3875 return (breakPatternCounter == 0);
3879- (BOOL) breakPatternHide
3882 return ((breakPatternCounter > 5)||(!player)||([player status] == STATUS_DOCKING));
3886#define PROFILE_SHIP_SELECTION 0
3889- (BOOL) canInstantiateShip:(NSString *)shipKey
3891 NSDictionary *shipInfo =
nil;
3892 NSArray *conditions =
nil;
3893 NSString *condition_script =
nil;
3896 condition_script = [shipInfo oo_stringForKey:@"condition_script"];
3897 if (condition_script !=
nil)
3899 OOJSScript *condScript = [
self getConditionScript:condition_script];
3900 if (condScript !=
nil)
3904 JSBool allow_instantiation;
3908 OK = [condScript
callMethod:OOJSID("allowSpawnShip")
3913 if (OK) OK = JS_ValueToBoolean(context, result, &allow_instantiation);
3917 if (OK && !allow_instantiation)
3927 conditions = [shipInfo oo_arrayForKey:@"conditions"];
3928 if (conditions ==
nil)
return YES;
3931 return [PLAYER scriptTestConditions:conditions];
3935- (NSString *) randomShipKeyForRoleRespectingConditions:(NSString *)role
3940 NSString *shipKey =
nil;
3943#if PROFILE_SHIP_SELECTION
3944 static unsigned long profTotal = 0, profSlowPath = 0;
3949 shipKey = [registry randomShipKeyForRole:role];
3950 if ([
self canInstantiateShip:shipKey])
return shipKey;
3959#if PROFILE_SHIP_SELECTION
3961 if ((profSlowPath % 10) == 0)
3963 OOLog(
@"shipRegistry.selection.profile",
@"Hit slow path in ship selection for role \"%@\
", having selected ship \"%@\". Now %lu of %lu on slow path (%f%%).", role, shipKey, profSlowPath, profTotal, ((
double)profSlowPath)/((
double)profTotal) * 100.0f);
3967 pset = [[[registry probabilitySetForRole:role] mutableCopy] autorelease];
3969 while ([pset
count] > 0)
3973 if ([
self canInstantiateShip:shipKey])
return shipKey;
3986- (
ShipEntity *) newShipWithRole:(NSString *)role
3991 NSString *shipKey =
nil;
3992 NSDictionary *shipInfo =
nil;
3993 NSString *autoAI =
nil;
3995 shipKey = [
self randomShipKeyForRoleRespectingConditions:role];
3998 ship = [
self newShipWithName:shipKey];
4001 [ship setPrimaryRole:role];
4004 if ([shipInfo oo_fuzzyBooleanForKey:
@"auto_ai" defaultValue:YES])
4007 autoAI = [
self defaultAIForRole:role];
4010 [ship setAITo:autoAI];
4013 if ([role isEqualToString:
@"pirate"]) [ship setBounty:20 + randf() * 50 withReason:kOOLegalStatusReasonSetup];
4014 if ([role isEqualToString:
@"trader"]) [ship setBounty:0 withReason:kOOLegalStatusReasonSetup];
4015 if ([role isEqualToString:
@"police"]) [ship setScanClass:CLASS_POLICE];
4016 if ([role isEqualToString:
@"interceptor"])
4018 [ship setScanClass: CLASS_POLICE];
4019 [ship setPrimaryRole:@"police"];
4022 if ([role isEqualToString:
@"thargoid"]) [ship setScanClass: CLASS_THARGOID];
4037 NSDictionary *effectDict =
nil;
4041 if (effectDict ==
nil)
return nil;
4047 @catch (NSException *exception)
4051 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newVisualEffectWithName: %@ ] *****", [exception reason], effectKey);
4053 else @throw exception;
4062- (
ShipEntity *) newSubentityWithName:(NSString *)shipKey andScaleFactor:(
float)scale
4064 return [
self newShipWithName:shipKey usePlayerProxy:NO isSubentity:YES andScaleFactor:scale];
4068- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy
4070 return [
self newShipWithName:shipKey usePlayerProxy:usePlayerProxy isSubentity:NO];
4073- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy isSubentity:(BOOL)isSubentity
4075 return [
self newShipWithName:shipKey usePlayerProxy:usePlayerProxy isSubentity:isSubentity andScaleFactor:1.0f];
4078- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy isSubentity:(BOOL)isSubentity andScaleFactor:(
float)scale
4082 NSDictionary *shipDict =
nil;
4086 if (shipDict ==
nil)
return nil;
4088 volatile Class shipClass =
nil;
4095 shipClass = [
self shipClassForShipDictionary:shipDict];
4096 if (usePlayerProxy && shipClass == [
ShipEntity class])
4106 NSMutableDictionary *mShipDict = [shipDict mutableCopy];
4107 [mShipDict setObject:[NSNumber numberWithFloat:scale] forKey:@"model_scale_factor"];
4108 shipDict = [NSDictionary dictionaryWithDictionary:mShipDict];
4109 [mShipDict release];
4111 ship = [[shipClass alloc] initWithKey:shipKey definition:shipDict];
4113 @catch (NSException *exception)
4117 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newShipWithName: %@ ] *****", [exception reason], shipKey);
4119 else @throw exception;
4132- (
DockEntity *) newDockWithName:(NSString *)shipDataKey andScaleFactor:(
float)scale
4136 NSDictionary *shipDict =
nil;
4140 if (shipDict ==
nil)
return nil;
4146 NSMutableDictionary *mShipDict = [shipDict mutableCopy];
4147 [mShipDict setObject:[NSNumber numberWithFloat:scale] forKey:@"model_scale_factor"];
4148 shipDict = [NSDictionary dictionaryWithDictionary:mShipDict];
4149 [mShipDict release];
4151 dock = [[
DockEntity alloc] initWithKey:shipDataKey definition:shipDict];
4153 @catch (NSException *exception)
4157 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newDockWithName: %@ ] *****", [exception reason], shipDataKey);
4159 else @throw exception;
4164 if ([dock hasRole:shipDataKey]) [dock
setPrimaryRole:shipDataKey];
4172- (
ShipEntity *) newShipWithName:(NSString *)shipKey
4174 return [
self newShipWithName:shipKey usePlayerProxy:NO];
4178- (Class) shipClassForShipDictionary:(NSDictionary *)dict
4182 if (dict ==
nil)
return Nil;
4184 BOOL isStation = NO;
4185 NSString *shipRoles = [dict oo_stringForKey:@"roles"];
4187 if (shipRoles !=
nil)
4189 isStation = [shipRoles rangeOfString:@"station"].location != NSNotFound ||
4190 [shipRoles rangeOfString:@"carrier"].location != NSNotFound;
4194 isStation = [dict oo_boolForKey:@"isCarrier" defaultValue:isStation];
4195 isStation = [dict oo_boolForKey:@"is_carrier" defaultValue:isStation];
4204- (NSString *)defaultAIForRole:(NSString *)role
4206 return [autoAIMap oo_stringForKey:role];
4221 foreach (itemData, equipmentData)
4223 NSString *itemType = [itemData oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
4225 if ([itemType isEqual:eq_key])
4227 return [itemData oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
4243 if ([cargoObj isTemplateCargoPod])
4245 return [UNIVERSE cargoPodFromTemplate:cargoObj];
4259 OOCargoQuantity co_amount = [UNIVERSE getRandomAmountOfCommodity:co_type];
4262 container = [UNIVERSE newShipWithRole:co_type];
4264 if (container ==
nil)
4266 container = [UNIVERSE newShipWithRole:@"cargopod"];
4269 return [container autorelease];
4273- (NSArray *) getContainersOfGoods:(
OOCargoQuantity)how_many scarce:(BOOL)scarce legal:(BOOL)legal
4279 NSMutableArray *accumulator = [NSMutableArray arrayWithCapacity:how_many];
4280 NSUInteger i=0, commodityCount = [commodityMarket count];
4284 NSArray *goodsKeys = [commodityMarket goods];
4285 NSString *goodsKey =
nil;
4287 foreach (goodsKey, goodsKeys)
4292 if (q < 64) q = 64 - q;
4297 if (legal && [commodityMarket exportLegalityForGood:goodsKey] > 0)
4303 quantities[i++] = q;
4304 total_quantity += q;
4307 for (i = 0; i < how_many; i++)
4309 NSUInteger co_type = 0;
4314 qr = 1+(
Ranrot() % total_quantity);
4318 NSAssert((NSUInteger)co_type < commodityCount,
@"Commodity type index out of range.");
4319 qr -= quantities[co_type++];
4324 ShipEntity *container = [cargoPods objectForKey:[goodsKeys oo_stringAtIndex:co_type]];
4326 if (container !=
nil)
4328 [accumulator addObject:container];
4332 OOLog(
@"universe.createContainer.failed",
@"***** ERROR: failed to find a container to fill with %@ (%ld).", [goodsKeys oo_stringAtIndex:co_type], co_type);
4336 return [NSArray arrayWithArray:accumulator];
4342 NSMutableArray *accumulator = [NSMutableArray arrayWithCapacity:how_much];
4343 if (![commodities goodDefined:commodity_name])
4345 return [NSArray array];
4348 ShipEntity *container = [cargoPods objectForKey:commodity_name];
4349 while (how_much > 0)
4353 [accumulator addObject:container];
4357 OOLog(
@"universe.createContainer.failed",
@"***** ERROR: failed to find a container to fill with %@", commodity_name);
4362 return [NSArray arrayWithArray:accumulator];
4366- (void) fillCargopodWithRandomCargo:(
ShipEntity *)cargopod
4368 if (cargopod ==
nil || ![cargopod hasRole:
@"cargopod"] || [cargopod cargoType] ==
CARGO_SCRIPTED_ITEM)
return;
4370 if ([cargopod commodityType] ==
nil || ![cargopod commodityAmount])
4372 NSString *aCommodity = [
self getRandomCommodity];
4373 OOCargoQuantity aQuantity = [
self getRandomAmountOfCommodity:aCommodity];
4379- (NSString *) getRandomCommodity
4381 return [commodities getRandomCommodity];
4389 if (co_type ==
nil) {
4393 units = [commodities massUnitForGood:co_type];
4403 OOLog(
@"universe.commodityAmount.warning",
@"Commodity %@ has an unrecognised mass unit, assuming tonnes",co_type);
4410 return [commodityMarket definitionForGood:type];
4416 return [commodityMarket nameForGood:co_type];
4423 NSString *unitDesc =
nil, *typeDesc =
nil;
4424 NSDictionary *commodity = [
self commodityDataForType:co_type];
4426 if (commodity ==
nil)
return @"";
4428 units = [commodityMarket massUnitForGood:co_type];
4434 unitDesc =
DESC(
@"cargo-kilogram");
4437 unitDesc =
DESC(
@"cargo-gram");
4441 unitDesc =
DESC(
@"cargo-ton");
4450 unitDesc =
DESC(
@"cargo-kilograms");
4453 unitDesc =
DESC(
@"cargo-grams");
4457 unitDesc =
DESC(
@"cargo-tons");
4462 typeDesc = [commodityMarket nameForGood:co_type];
4464 return [NSString stringWithFormat:@"%d %@ %@",co_amount, unitDesc, typeDesc];
4472 gameView = [view retain];
4484 return [[
self gameView] gameController];
4488- (NSDictionary *) gameSettings
4491 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:11];
4493 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:10];
4496 [result oo_setInteger:[PLAYER isSpeechOn] forKey:@"speechOn"];
4497 [result oo_setBool:autoSave forKey:@"autosave"];
4498 [result oo_setBool:wireframeGraphics forKey:@"wireframeGraphics"];
4499 [result oo_setBool:doProcedurallyTexturedPlanets forKey:@"procedurallyTexturedPlanets"];
4501 [result oo_setFloat:[gameView gammaValue] forKey:@"gammaValue"];
4504 [result oo_setFloat:[gameView fov:NO] forKey:@"fovValue"];
4507 if ([gameView hdrOutput])
4509 [result oo_setFloat:[gameView hdrMaxBrightness] forKey:@"hdr-max-brightness"];
4510 [result oo_setFloat:[gameView hdrPaperWhiteBrightness] forKey:@"hdr-paperwhite-brightness"];
4514 [result setObject:OOStringFromGraphicsDetail([
self detailLevel]) forKey:@"detailLevel"];
4516 NSString *desc =
@"UNDEFINED";
4523 [result setObject:desc forKey:@"musicMode"];
4525 NSDictionary *gameWindow = [NSDictionary dictionaryWithObjectsAndKeys:
4526 [NSNumber numberWithFloat:[gameView viewSize].width], @"width",
4527 [NSNumber numberWithFloat:[gameView viewSize].height], @"height",
4528 [NSNumber numberWithBool:[[
self gameController] inFullScreenMode]], @"fullScreen",
4530 [result setObject:gameWindow forKey:@"gameWindow"];
4532 [result setObject:[PLAYER keyConfig] forKey:@"keyConfig"];
4534 return [[result copy] autorelease];
4538- (void) useGUILightSource:(BOOL)GUILight
4542 if (![
self useShaders])
4546 OOGL(glEnable(GL_LIGHT0));
4547 OOGL(glDisable(GL_LIGHT1));
4551 OOGL(glEnable(GL_LIGHT1));
4552 OOGL(glDisable(GL_LIGHT0));
4561 else OOGL(glEnable(GL_LIGHT1));
4568- (void) lightForEntity:(BOOL)isLit
4572 if ([
self useShaders])
4576 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
4577 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
4589 if (isLit)
OOGL(glEnable(GL_LIGHT1));
4590 else OOGL(glDisable(GL_LIGHT1));
4595 OOGL(glEnable(GL_LIGHT0));
4611 { 1.0f, 0.0f, 0.0f, 0.0f },
4612 { 0.0f, 1.0f, 0.0f, 0.0f },
4613 { 0.0f, 0.0f, 1.0f, 0.0f },
4614 { 0.0f, 0.0f, 0.0f, 1.0f }
4618 {-1.0f, 0.0f, 0.0f, 0.0f },
4619 { 0.0f, 1.0f, 0.0f, 0.0f },
4620 { 0.0f, 0.0f, -1.0f, 0.0f },
4621 { 0.0f, 0.0f, 0.0f, 1.0f }
4625 { 0.0f, 0.0f, -1.0f, 0.0f },
4626 { 0.0f, 1.0f, 0.0f, 0.0f },
4627 { 1.0f, 0.0f, 0.0f, 0.0f },
4628 { 0.0f, 0.0f, 0.0f, 1.0f }
4632 { 0.0f, 0.0f, 1.0f, 0.0f },
4633 { 0.0f, 1.0f, 0.0f, 0.0f },
4634 {-1.0f, 0.0f, 0.0f, 0.0f },
4635 { 0.0f, 0.0f, 0.0f, 1.0f }
4639- (void) getActiveViewMatrix:(OOMatrix *)outMatrix forwardVector:(Vector *)outForward upVector:(Vector *)outUp
4641 assert(outMatrix != NULL && outForward != NULL && outUp != NULL);
4645 switch (viewDirection)
4659 case VIEW_STARBOARD:
4674 case VIEW_GUI_DISPLAY:
4675 case VIEW_BREAK_PATTERN:
4685- (OOMatrix) activeViewMatrix
4690 [
self getActiveViewMatrix:&m forwardVector:&f upVector:&u];
4700- (void) defineFrustum
4708 frustum[0][0] = clip.m[0][3] - clip.m[0][0];
4709 frustum[0][1] = clip.m[1][3] - clip.m[1][0];
4710 frustum[0][2] = clip.m[2][3] - clip.m[2][0];
4711 frustum[0][3] = clip.m[3][3] - clip.m[3][0];
4714 rt = 1.0f / sqrt(frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2]);
4715 frustum[0][0] *= rt;
4716 frustum[0][1] *= rt;
4717 frustum[0][2] *= rt;
4718 frustum[0][3] *= rt;
4721 frustum[1][0] = clip.m[0][3] + clip.m[0][0];
4722 frustum[1][1] = clip.m[1][3] + clip.m[1][0];
4723 frustum[1][2] = clip.m[2][3] + clip.m[2][0];
4724 frustum[1][3] = clip.m[3][3] + clip.m[3][0];
4727 rt = 1.0f / sqrt(frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2]);
4728 frustum[1][0] *= rt;
4729 frustum[1][1] *= rt;
4730 frustum[1][2] *= rt;
4731 frustum[1][3] *= rt;
4734 frustum[2][0] = clip.m[0][3] + clip.m[0][1];
4735 frustum[2][1] = clip.m[1][3] + clip.m[1][1];
4736 frustum[2][2] = clip.m[2][3] + clip.m[2][1];
4737 frustum[2][3] = clip.m[3][3] + clip.m[3][1];
4740 rt = 1.0 / sqrt(frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2]);
4741 frustum[2][0] *= rt;
4742 frustum[2][1] *= rt;
4743 frustum[2][2] *= rt;
4744 frustum[2][3] *= rt;
4747 frustum[3][0] = clip.m[0][3] - clip.m[0][1];
4748 frustum[3][1] = clip.m[1][3] - clip.m[1][1];
4749 frustum[3][2] = clip.m[2][3] - clip.m[2][1];
4750 frustum[3][3] = clip.m[3][3] - clip.m[3][1];
4753 rt = 1.0 / sqrt(frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2]);
4754 frustum[3][0] *= rt;
4755 frustum[3][1] *= rt;
4756 frustum[3][2] *= rt;
4757 frustum[3][3] *= rt;
4760 frustum[4][0] = clip.m[0][3] - clip.m[0][2];
4761 frustum[4][1] = clip.m[1][3] - clip.m[1][2];
4762 frustum[4][2] = clip.m[2][3] - clip.m[2][2];
4763 frustum[4][3] = clip.m[3][3] - clip.m[3][2];
4766 rt = sqrt(frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2]);
4767 frustum[4][0] *= rt;
4768 frustum[4][1] *= rt;
4769 frustum[4][2] *= rt;
4770 frustum[4][3] *= rt;
4773 frustum[5][0] = clip.m[0][3] + clip.m[0][2];
4774 frustum[5][1] = clip.m[1][3] + clip.m[1][2];
4775 frustum[5][2] = clip.m[2][3] + clip.m[2][2];
4776 frustum[5][3] = clip.m[3][3] + clip.m[3][2];
4779 rt = sqrt(frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2]);
4780 frustum[5][0] *= rt;
4781 frustum[5][1] *= rt;
4782 frustum[5][2] *= rt;
4783 frustum[5][3] *= rt;
4787- (BOOL) viewFrustumIntersectsSphereAt:(Vector)position withRadius:(GLfloat)radius
4791 for (p = 0; p < 6; p++)
4793 if (frustum[p][0] * position.x + frustum[p][1] * position.y + frustum[p][2] * position.z + frustum[p][3] <= -radius)
4802- (void) drawUniverse
4804 int currentPostFX = [
self currentPostFX];
4806 NSSize viewSize = [gameView viewSize];
4807 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin draw");
4811 if ((
int)targetFramebufferSize.width != (
int)viewSize.width || (
int)targetFramebufferSize.height != (
int)viewSize.height)
4813 [
self resizeTargetFramebufferWithViewSize:viewSize];
4816 if([
self useShaders])
4818 if ([gameView msaa])
4820 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
4824 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
4831 int i, v_status, vdist;
4832 Vector view_dir, view_up;
4833 OOMatrix view_matrix;
4834 int ent_count = n_entities;
4835 Entity *my_entities[ent_count];
4841 float aspect = viewSize.height/viewSize.width;
4843 if (!displayGUI && wasDisplayGUI)
4846 if (cachedSun) [UNIVERSE setMainLightPosition:HPVectorToVector([cachedSun position])];
4847 else [UNIVERSE setMainLightPosition:kZeroVector];
4849 wasDisplayGUI = displayGUI;
4851 for (i = 0; i < ent_count; i++)
4858 Entity *e = sortedEntities[i];
4861 my_entities[draw_count++] = [[e retain] autorelease];
4865 v_status = [player
status];
4871 OOGL(glClear(GL_COLOR_BUFFER_BIT));
4875 OOGL(glClearColor(skyClearColor[0], skyClearColor[1], skyClearColor[2], skyClearColor[3]));
4879 OOGL(glClearColor(0.0, 0.0, 0.0, 0.0));
4883 [gui drawGUIBackground];
4887 BOOL fogging, bpHide = [
self breakPatternHide];
4889 for (vdist=0;vdist<=1;vdist++)
4893 float ratio = (displayGUI ? 0.5 : [gameView fov:YES]) * nearPlane;
4896 if ((displayGUI && 4*aspect >= 3) || (!displayGUI && 4*aspect <= 3))
4898 OOGLFrustum(-ratio, ratio, -aspect*ratio, aspect*ratio, nearPlane, farPlane);
4902 OOGLFrustum(-3*ratio/aspect/4, 3*ratio/aspect/4, -3*ratio/4, 3*ratio/4, nearPlane, farPlane);
4905 [
self getActiveViewMatrix:&view_matrix forwardVector:&view_dir upVector:&view_up];
4937 OOGL(glClear(GL_DEPTH_BUFFER_BIT));
4942 flipMatrix.m[2][2] = -1;
4948 if (
EXPECT(!displayGUI || demoShipMode))
4950 if (
EXPECT(!demoShipMode))
4956 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
4960 [
self setMainLightPosition:[cachedSun cameraRelativePosition]];
4965 [
self setMainLightPosition:HPVectorToVector(HPvector_flip([PLAYER viewpointPosition]))];
4967 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, main_light_position));
4973 OOGL(glLightfv(GL_LIGHT0, GL_POSITION, main_light_position));
4975 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, main_light_position));
4979 OOGL([
self useGUILightSource:demoShipMode]);
4984 int furthest = draw_count - 1;
4986 BOOL inAtmosphere = airResistanceFactor > 0.01;
4987 GLfloat fogFactor = 0.5 / airResistanceFactor;
4988 double fog_scale, half_scale;
4989 GLfloat flat_ambdiff[4] = {1.0, 1.0, 1.0, 1.0};
4990 GLfloat mat_no[4] = {0.0, 0.0, 0.0, 1.0};
4993 OOGL(glHint(GL_FOG_HINT, [
self reducedDetail] ? GL_FASTEST : GL_NICEST));
4995 [
self defineFrustum];
4999 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin opaque pass");
5003 for (i = furthest; i >= nearest; i--)
5005 drawthing = my_entities[i];
5009 if (vdist == 1 && [drawthing cameraRangeFront] > farPlane*1.5)
continue;
5010 if (vdist == 0 && [drawthing cameraRangeBack] < nearPlane)
continue;
5013 if (!((d_status == STATUS_COCKPIT_DISPLAY) ^ demoShipMode))
5017 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, flat_ambdiff));
5018 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_no));
5021 if (
EXPECT(drawthing != player))
5044 half_scale = fog_scale * 0.50;
5045 OOGL(glEnable(GL_FOG));
5046 OOGL(glFogi(GL_FOG_MODE, GL_LINEAR));
5047 OOGL(glFogfv(GL_FOG_COLOR, skyClearColor));
5048 OOGL(glFogf(GL_FOG_START, half_scale));
5049 OOGL(glFogf(GL_FOG_END, fog_scale));
5050 fog_blend = OOClamp_0_1_f((magnitude([drawthing cameraRelativePosition]) - half_scale)/half_scale);
5054 [
self lightForEntity:demoShipMode || drawthing->isSunlit];
5065 OOGL(glDisable(GL_FOG));
5070 if (!((d_status == STATUS_COCKPIT_DISPLAY) ^ demoShipMode))
5073 if (
EXPECT(drawthing != player))
5096 half_scale = fog_scale * 0.50;
5097 OOGL(glEnable(GL_FOG));
5098 OOGL(glFogi(GL_FOG_MODE, GL_LINEAR));
5099 OOGL(glFogfv(GL_FOG_COLOR, skyClearColor));
5100 OOGL(glFogf(GL_FOG_START, half_scale));
5101 OOGL(glFogf(GL_FOG_END, fog_scale));
5102 fog_blend = OOClamp_0_1_f((magnitude([drawthing cameraRelativePosition]) - half_scale)/half_scale);
5113 OOGL(glDisable(GL_FOG));
5130 if (!bpHide && cachedSun)
5132 [cachedSun drawDirectVisionSunGlare];
5133 [cachedSun drawStarGlare];
5138 if (hudSeparateRenderPass)
5143 [
self prepareToRenderIntoDefaultFramebuffer];
5144 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
5146 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"Begin second pass draw");
5147 [
self drawTargetTextureIntoDefaultFramebuffer];
5148 OOCheckOpenGLErrors(
@"Universe after drawing from custom framebuffer to screen framebuffer");
5149 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"End second pass drawing");
5151 OOLog(
@"universe.profile.drawHUD",
@"%@",
@"Begin HUD drawing");
5156 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin HUD");
5158 GLfloat lineWidth = [gameView viewSize].width / 1024.0;
5159 if (lineWidth < 1.0) lineWidth = 1.0;
5160 if (lineWidth > 1.5) lineWidth = 1.5;
5167 if ([theHUD deferredHudName] !=
nil)
5171 [deferredName release];
5172 theHUD = [player
hud];
5176 static float sPrevHudAlpha = -1.0f;
5177 if ([theHUD isHidden])
5179 if (sPrevHudAlpha < 0.0f)
5185 else if (sPrevHudAlpha >= 0.0f)
5188 sPrevHudAlpha = -1.0f;
5193 case STATUS_ESCAPE_SEQUENCE:
5194 case STATUS_START_GAME:
5198 switch ([player guiScreen])
5212#if (defined (SNAPSHOT_BUILD) && defined (OOLITE_SNAPSHOT_VERSION))
5213 [
self drawWatermarkString:@"Development version " @OOLITE_SNAPSHOT_VERSION];
5216 OOLog(
@"universe.profile.drawHUD",
@"%@",
@"End HUD drawing");
5225 if (![[
self gameController] isGamePaused])
5227 framesDoneThisUpdate++;
5230 @catch (NSException *exception)
5234 if ([[exception name] hasPrefix:
@"Oolite"])
5236 [
self handleOoliteException:exception];
5240 OOLog(
kOOLogException,
@"***** Exception: %@ : %@ *****",[exception name], [exception reason]);
5246 OOLog(
@"universe.profile.draw",
@"%@",
@"End drawing");
5249 if(!hudSeparateRenderPass)
5251 if([
self useShaders])
5253 [
self prepareToRenderIntoDefaultFramebuffer];
5254 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
5256 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"Begin second pass draw");
5257 [
self drawTargetTextureIntoDefaultFramebuffer];
5258 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"End second pass drawing");
5266 NSSize viewSize = [gameView viewSize];
5267 if([
self useShaders])
5269 if ([gameView msaa])
5272 OOGL(glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFramebufferID));
5273 OOGL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFramebufferID));
5274 OOGL(glBlitFramebuffer(0, 0, (GLint)viewSize.width, (GLint)viewSize.height, 0, 0, (GLint)viewSize.width, (GLint)viewSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
5280- (
int) framesDoneThisUpdate
5282 return framesDoneThisUpdate;
5286- (void) resetFramesDoneThisUpdate
5288 framesDoneThisUpdate = 0;
5292- (OOMatrix) viewMatrix
5302 OOGL(glDisable(GL_TEXTURE_2D));
5304 float overallAlpha = [[PLAYER hud] overallAlpha];
5309 cursor_row = [gui drawGUI:1.0 drawCursor:YES];
5313 [gui drawGUI:1.0 drawCursor:NO];
5317 [message_gui drawGUI:[message_gui alpha] * overallAlpha drawCursor:NO];
5318 [comm_log_gui drawGUI:[comm_log_gui alpha] * overallAlpha drawCursor:NO];
5324- (void) drawWatermarkString:(NSString *) watermarkString
5326 NSSize watermarkStringSize =
OORectFromString(watermarkString, 0.0f, 0.0f, NSMakeSize(10, 10)).size;
5328 OOGL(glColor4f(0.0, 1.0, 0.0, 1.0));
5342 OOLog(
@"universe.badUID",
@"Attempt to retrieve entity for out-of-range UID %u. (This is an internal programming error, please report it.)", u_id);
5346 if ((u_id ==
NO_TARGET)||(!entity_for_uid[u_id]))
5349 Entity *ent = entity_for_uid[u_id];
5355 if ([ent status] == STATUS_DEAD || [ent status] == STATUS_DOCKED)
5366 NSCParameterAssert(uni != NULL);
5379 while ((n--)&&(checkEnt))
5382 checkEnt = checkEnt->
x_next;
5384 if ((checkEnt)||(n > 0))
5392 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
x_previous;
5393 if ((checkEnt)||(n > 0))
5404 checkEnt = checkEnt->
x_next;
5412 while ((n--)&&(checkEnt))
5415 checkEnt = checkEnt->
y_next;
5417 if ((checkEnt)||(n > 0))
5425 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
y_previous;
5426 if ((checkEnt)||(n > 0))
5437 checkEnt = checkEnt->
y_next;
5445 while ((n--)&&(checkEnt))
5448 checkEnt = checkEnt->
z_next;
5450 if ((checkEnt)||(n > 0))
5458 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
z_previous;
5459 if ((checkEnt)||(n > 0))
5466 NSCAssert(checkEnt !=
nil,
@"Expected z-list to be non-empty.");
5471 checkEnt = checkEnt->
z_next;
5481 NSArray *allEntities = uni->
entities;
5487 foreach (ent, allEntities)
5503- (BOOL) addEntity:(
Entity *) entity
5511 if (![entity validForAddToUniverse])
return NO;
5514 if ([entities containsObject:entity])
5520 OOLog(
@"universe.addEntity.failed",
@"***** Universe cannot addEntity:%@ -- Universe is full (%d entities out of %d)", entity, n_entities,
UNIVERSE_MAX_ENTITIES);
5527 if (![entity isEffect])
5530 while (entity_for_uid[next_universal_id] !=
nil)
5532 next_universal_id++;
5540 OOLog(
@"universe.addEntity.failed",
@"***** Universe cannot addEntity:%@ -- Could not find free slot for entity.", entity);
5544 [entity setUniversalID:next_universal_id];
5545 entity_for_uid[next_universal_id] = entity;
5546 if ([entity isShip])
5551 [
self setNextBeacon:se];
5558 double stationRoll = 0.0;
5562 if (definedRoll !=
nil)
5568 stationRoll = [[
self currentSystemData] oo_doubleForKey:@"station_roll" defaultValue:STANDARD_STATION_ROLL];
5581 if ([se status] != STATUS_COCKPIT_DISPLAY)
5589 [entity setUniversalID:NO_TARGET];
5590 if ([entity isVisualEffect])
5595 [
self setNextBeacon:ve];
5598 else if ([entity isWaypoint])
5603 [
self setNextBeacon:wp];
5613 [entities addObject:entity];
5614 [entity wasAddedToUniverse];
5617 HPVector entity_pos = entity->position;
5618 HPVector delta = HPvector_between(entity_pos,
PLAYER->position);
5619 double z_distance = HPmagnitude2(delta);
5620 entity->zero_distance = z_distance;
5621 unsigned index = n_entities;
5622 sortedEntities[index] = entity;
5623 entity->zero_index = index;
5624 while ((index > 0)&&(z_distance < sortedEntities[index - 1]->zero_distance))
5626 sortedEntities[index] = sortedEntities[index - 1];
5627 sortedEntities[index]->zero_index = index;
5629 sortedEntities[index] = entity;
5630 entity->zero_index = index;
5637 [entity addToLinkedLists];
5638 if ([entity canCollide])
5640 doLinkedListMaintenanceThisUpdate = YES;
5643 if ([entity isWormhole])
5645 [activeWormholes addObject:entity];
5647 else if ([entity isPlanet])
5649 [allPlanets addObject:entity];
5651 else if ([entity isShip])
5655 if ([entity isStation])
5657 [allStations addObject:entity];
5667- (BOOL) removeEntity:(
Entity *) entity
5669 if (entity !=
nil && ![entity isPlayer])
5675 [entitiesDeadThisUpdate addObject:entity];
5676 if ([entity isStation])
5678 [allStations removeObject:entity];
5679 if ([
PLAYER getTargetDockStation] == entity)
5681 [PLAYER setDockingClearanceStatus:DOCKING_CLEARANCE_STATUS_NONE];
5684 return [
self doRemoveEntity:entity];
5690- (void) ensureEntityReallyRemoved:(
Entity *)entity
5694 OOLog(
@"universe.unremovedEntity",
@"Entity %@ dealloced without being removed from universe! (This is an internal programming error, please report it.)", entity);
5695 [
self doRemoveEntity:entity];
5700- (void) removeAllEntitiesExceptPlayer
5702 BOOL updating = no_update;
5706 Entity* p0 = [entities objectAtIndex:0];
5715 NSMutableArray *savedWormholes = [activeWormholes mutableCopy];
5717 while ([entities
count] > 1)
5719 Entity* ent = [entities objectAtIndex:1];
5722 if (
EXPECT(![ent isVisualEffect]))
5724 [
self removeEntity:ent];
5733 [activeWormholes release];
5734 activeWormholes = savedWormholes;
5741 cachedStation =
nil;
5742 [closeSystems release];
5745 [
self resetBeacons];
5746 [waypoints removeAllObjects];
5748 no_update = updating;
5752- (void) removeDemoShips
5755 int ent_count = n_entities;
5759 for (i = 0; i < ent_count; i++)
5761 ent = sortedEntities[i];
5762 if ([ent status] == STATUS_COCKPIT_DISPLAY && ![ent isPlayer])
5764 [
self removeEntity:ent];
5772- (
ShipEntity *) makeDemoShipWithRole:(NSString *)role spinning:(BOOL)spinning
5776 [
self removeDemoShips];
5778 [PLAYER setShowDemoShips: YES];
5779 Quaternion q2 = { (GLfloat)
M_SQRT1_2, (GLfloat)
M_SQRT1_2, (GLfloat)0.0, (GLfloat)0.0 };
5781 ShipEntity *ship = [
self newShipWithRole:role];
5791 [UNIVERSE addEntity:ship];
5801 [ship
setStatus:STATUS_COCKPIT_DISPLAY];
5808 return [ship autorelease];
5812- (BOOL) isVectorClearFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5820 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5822 double nearest = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z) - dist;
5828 int ent_count = n_entities;
5829 Entity* my_entities[ent_count];
5830 for (i = 0; i < ent_count; i++)
5831 my_entities[i] = [sortedEntities[i] retain];
5833 if (v1.x || v1.y || v1.z)
5834 f1 = HPvector_normal(v1);
5836 f1 = make_HPvector(0, 0, 1);
5838 for (i = 0; i < ent_count ; i++)
5840 Entity *e2 = my_entities[i];
5841 if ((e2 != e1)&&([e2 canCollide]))
5844 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5846 double d_forward = HPdot_product(epos,f1);
5848 if ((d_forward > 0)&&(d_forward < nearest))
5852 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5855 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5857 double dist2 = p0.x * p0.x + p0.
y * p0.
y + p0.z * p0.z;
5860 for (i = 0; i < ent_count; i++)
5861 [my_entities[i] release];
5867 for (i = 0; i < ent_count; i++)
5868 [my_entities[i] release];
5873- (
Entity*) hazardOnRouteFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5881 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5883 double nearest = HPmagnitude(v1) - dist;
5890 int ent_count = n_entities;
5891 Entity* my_entities[ent_count];
5892 for (i = 0; i < ent_count; i++)
5893 my_entities[i] = [sortedEntities[i] retain];
5895 if (v1.x || v1.y || v1.z)
5896 f1 = HPvector_normal(v1);
5898 f1 = make_HPvector(0, 0, 1);
5900 for (i = 0; (i < ent_count) && (!result) ; i++)
5902 Entity *e2 = my_entities[i];
5903 if ((e2 != e1)&&([e2 canCollide]))
5906 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5908 double d_forward = HPdot_product(epos,f1);
5910 if ((d_forward > 0)&&(d_forward < nearest))
5914 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5917 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5919 double dist2 = HPmagnitude2(p0);
5925 for (i = 0; i < ent_count; i++)
5926 [my_entities[i] release];
5931- (HPVector) getSafeVectorFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5942 HPVector result = p2;
5944 int ent_count = n_entities;
5945 Entity* my_entities[ent_count];
5946 for (i = 0; i < ent_count; i++)
5947 my_entities[i] = [sortedEntities[i] retain];
5950 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5952 double nearest = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z) - dist;
5954 if (v1.x || v1.y || v1.z)
5955 f1 = HPvector_normal(v1);
5957 f1 = make_HPvector(0, 0, 1);
5959 for (i = 0; i < ent_count; i++)
5961 Entity *e2 = my_entities[i];
5962 if ((e2 != e1)&&([e2 canCollide]))
5965 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5966 double d_forward = HPdot_product(epos,f1);
5967 if ((d_forward > 0)&&(d_forward < nearest))
5972 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5976 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5979 double dist2 = p0.x * p0.x + p0.
y * p0.
y + p0.z * p0.z;
5984 nearest = d_forward;
5990 result.x += ((
int)(
Ranrot() % 1024) - 512)/512.0;
5991 result.y += ((
int)(
Ranrot() % 1024) - 512)/512.0;
5992 result.z += ((
int)(
Ranrot() % 1024) - 512)/512.0;
5995 HPVector nearest_point = p1;
5996 nearest_point.x += d_forward * f1.
x; nearest_point.y += d_forward * f1.
y; nearest_point.z += d_forward * f1.z;
5999 HPVector outward = nearest_point;
6000 outward.x -= result.
x; outward.y -= result.
y; outward.z -= result.z;
6001 if (outward.x||outward.y||outward.z)
6002 outward = HPvector_normal(outward);
6007 HPVector backward = p1;
6008 backward.x -= result.
x; backward.y -= result.
y; backward.z -= result.z;
6009 if (backward.x||backward.y||backward.z)
6010 backward = HPvector_normal(backward);
6015 HPVector dd = result;
6016 dd.x -= p1.
x; dd.y -= p1.
y; dd.z -= p1.z;
6017 double current_distance = HPmagnitude(dd);
6020 if (current_distance < cr * 1.25)
6021 current_distance = cr * 1.25;
6022 if (current_distance > cr * 5.0)
6023 current_distance = cr * 5.0;
6027 result.x += 0.25 * (outward.
x * current_distance) + 0.75 * (backward.
x * current_distance);
6028 result.y += 0.25 * (outward.
y * current_distance) + 0.75 * (backward.
y * current_distance);
6029 result.z += 0.25 * (outward.z * current_distance) + 0.75 * (backward.z * current_distance);
6035 for (i = 0; i < ent_count; i++)
6036 [my_entities[i] release];
6041- (
ShipEntity*) addWreckageFrom:(
ShipEntity *)ship withRole:(NSString *)wreckRole at:(HPVector)rpos scale:(GLfloat)scale lifetime:(GLfloat)lifetime
6043 ShipEntity* wreck = [UNIVERSE newShipWithRole:wreckRole];
6047 GLfloat expected_mass = 0.1f * [ship
mass] * (0.75 + 0.5 *
randf());
6048 GLfloat wreck_mass = [wreck
mass];
6049 GLfloat scale_factor = powf(expected_mass / wreck_mass, 0.33333333f) * scale;
6065 [UNIVERSE addEntity:wreck];
6075- (void) addLaserHitEffectsAt:(HPVector)pos against:(
ShipEntity *)target damage:(
float)damage color:(
OOColor *)color
6078 if ([target showDamage] && [target energy] < [target maxEnergy]/2)
6080 NSString *key = (
randf() < 0.5) ?
@"oolite-hull-spark" :
@"oolite-hull-spark-b";
6081 NSDictionary *settings = [UNIVERSE explosionSetting:key];
6084 [
self addEntity: burst];
6085 if ([target energy] *
randf() < damage)
6087 ShipEntity *wreck = [
self addWreckageFrom:target withRole:@"oolite-wreckage-chunk" at:pos scale:0.05 lifetime:(125.0+(randf()*200.0))];
6090 Vector direction = HPVectorToVector(HPvector_normal(HPvector_subtract(pos,[target position])));
6091 [wreck
setVelocity:vector_add([wreck
velocity],vector_multiply_scalar(direction,10+20*randf()))];
6102- (
ShipEntity *) firstShipHitByLaserFromShip:(
ShipEntity *)srcEntity inDirection:(
OOWeaponFacing)direction offset:(Vector)offset gettingRangeFound:(GLfloat *)range_ptr
6104 if (srcEntity ==
nil)
return nil;
6108 HPVector p0 = [srcEntity
position];
6116 HPVector midfrontplane = make_HPvector(0.5 * (bbox.max.x + bbox.min.x), 0.5 * (bbox.max.y + bbox.min.y), bbox.max.z);
6119 if ([parent isPlayer]) q1.w = -q1.w;
6124 int ent_count = n_entities;
6128 for (i = 0; i < ent_count; i++)
6130 Entity* ent = sortedEntities[i];
6131 if (ent != srcEntity && ent != parent && [ent isShip] && [ent canCollide])
6162 HPVector p1 = HPvector_add(p0, vectorToHPVector(vector_multiply_scalar(f1, nearest)));
6164 for (i = 0; i < ship_count; i++)
6170 Vector rpos = HPVectorToVector(HPvector_subtract(e2->
position, p0));
6171 Vector v_off = make_vector(dot_product(rpos, r1), dot_product(rpos, u1), dot_product(rpos, f1));
6172 if (v_off.z > 0.0 && v_off.z < nearest + cr &&
6173 v_off.x < cr && v_off.x > -cr && v_off.y < cr && v_off.y > -cr &&
6174 v_off.x * v_off.x + v_off.y * v_off.y < cr * cr)
6177 GLfloat hit = [(
ShipEntity *)
e2 doesHitLine:p0 :p1 :&entHit];
6179 if (hit > 0.0 && hit < nearest)
6181 if ([entHit isSubEntity])
6183 hit_subentity = entHit;
6187 p1 = HPvector_add(p0, vectorToHPVector(vector_multiply_scalar(f1, nearest)));
6197 if (range_ptr != NULL)
6199 *range_ptr = nearest;
6203 for (i = 0; i < ship_count; i++) [my_entities[i] release];
6209- (
Entity *) firstEntityTargetedByPlayer
6214 nearest2 *= nearest2;
6216 int ent_count = n_entities;
6218 Entity *my_entities[ent_count];
6220 for (i = 0; i < ent_count; i++)
6222 if (([sortedEntities[i] isShip] && ![sortedEntities[i] isPlayer]) || [sortedEntities[i] isWormhole])
6224 my_entities[ship_count++] = [sortedEntities[i] retain];
6236 switch (viewDirection)
6244 case VIEW_STARBOARD :
6252 for (i = 0; i < ship_count; i++)
6254 Entity *e2 = my_entities[i];
6255 if ([e2 canCollide] && [e2 scanClass] != CLASS_NO_DRAW)
6257 Vector rp = HPVectorToVector(HPvector_subtract([e2 position], p1));
6259 if (dist2 < nearest2)
6262 if (df > 0.0 && df * df < nearest2)
6267 if (du * du + dr * dr < cr * cr)
6277 if (hit_entity !=
nil && [hit_entity isShip])
6280 if ([ship isJammingScanning] && ![player hasMilitaryScannerFilter])
6286 for (i = 0; i < ship_count; i++)
6288 [my_entities[i] release];
6295- (
Entity *) firstEntityTargetedByPlayerPrecisely
6301 switch (viewDirection)
6318 case VIEW_STARBOARD:
6329 return [
self firstShipHitByLaserFromShip:PLAYER inDirection:targetFacing offset:laserPortOffset gettingRangeFound:NULL];
6333- (NSArray *) entitiesWithinRange:(
double)range ofEntity:(
Entity *)entity
6335 if (entity ==
nil)
return nil;
6337 return [
self findShipsMatchingPredicate:YESPredicate
6344- (unsigned) countShipsWithRole:(NSString *)role inRange:(
double)range ofEntity:(
Entity *)entity
6346 return [
self countShipsMatchingPredicate:HasRolePredicate
6353- (unsigned) countShipsWithRole:(NSString *)role
6355 return [
self countShipsWithRole:role inRange:-1 ofEntity:nil];
6359- (unsigned) countShipsWithPrimaryRole:(NSString *)role inRange:(
double)range ofEntity:(
Entity *)entity
6361 return [
self countShipsMatchingPredicate:HasPrimaryRolePredicate
6368- (unsigned) countShipsWithScanClass:(
OOScanClass)scanClass inRange:(
double)range ofEntity:(
Entity *)entity
6370 return [
self countShipsMatchingPredicate:HasScanClassPredicate
6371 parameter:[NSNumber numberWithInt:scanClass]
6377- (unsigned) countShipsWithPrimaryRole:(NSString *)role
6379 return [
self countShipsWithPrimaryRole:role inRange:-1 ofEntity:nil];
6384 parameter:(
void *)parameter
6385 inRange:(
double)range
6388 unsigned i, found = 0;
6390 double distance, cr;
6397 for (i = 0; i < n_entities; i++)
6399 Entity *e2 = sortedEntities[i];
6400 if (e2 != e1 && predicate(e2, parameter))
6402 if (range < 0) distance = -1;
6405 cr = range + e2->collision_radius;
6406 distance = HPdistance2(e2->
position, p1) - cr * cr;
6420 parameter:(
void *)parameter
6421 inRange:(
double)range
6422 ofEntity:(
Entity *)entity
6424 if (predicate != NULL)
6429 predicate, parameter
6432 return [
self countEntitiesMatchingPredicate:ANDPredicate
6439 return [
self countEntitiesMatchingPredicate:IsShipPredicate
6449 if (range < 0)
return YES;
6451 return HPdistance2(e2->
position,p1) < cr * cr;
6458 parameter:(
void *)parameter
6459 inRange:(
double)range
6466 NSMutableArray *result =
nil;
6472 result = [NSMutableArray arrayWithCapacity:n_entities];
6477 for (i = 0; i < n_entities; i++)
6479 Entity *e2 = sortedEntities[i];
6483 predicate(e2, parameter))
6485 [result addObject:e2];
6498 parameter:(
void *)parameter
6507 for (i = 0; i < n_entities; i++)
6509 candidate = sortedEntities[i];
6510 if (predicate(candidate, parameter))
return candidate;
6520 parameter:(
void *)parameter
6521 inRange:(
double)range
6522 ofEntity:(
Entity *)entity
6524 if (predicate != NULL)
6529 predicate, parameter
6532 return [
self findEntitiesMatchingPredicate:ANDPredicate
6539 return [
self findEntitiesMatchingPredicate:IsShipPredicate
6548 parameter:(
void *)parameter
6549 inRange:(
double)range
6550 ofEntity:(
Entity *)entity
6552 if (predicate != NULL)
6557 predicate, parameter
6560 return [
self findEntitiesMatchingPredicate:ANDPredicate
6567 return [
self findEntitiesMatchingPredicate:IsVisualEffectPredicate
6576 parameter:(
void *)parameter
6577 relativeToEntity:(
Entity *)entity
6581 float rangeSq = INFINITY;
6589 for (i = 0; i < n_entities; i++)
6591 Entity *e2 = sortedEntities[i];
6592 float distanceToReferenceEntitySquared = (float)HPdistance2(p1, [e2 position]);
6595 distanceToReferenceEntitySquared < rangeSq &&
6596 predicate(e2, parameter))
6599 rangeSq = distanceToReferenceEntitySquared;
6603 return [[result retain] autorelease];
6608 parameter:(
void *)parameter
6609 relativeToEntity:(
Entity *)entity
6611 if (predicate != NULL)
6616 predicate, parameter
6619 return [
self nearestEntityMatchingPredicate:ANDPredicate
6621 relativeToEntity:entity];
6625 return [
self nearestEntityMatchingPredicate:IsShipPredicate
6627 relativeToEntity:entity];
6634 return universal_time;
6644- (void) findCollisionsAndShadows
6648 [universeRegion clearEntityList];
6650 for (i = 0; i < n_entities; i++)
6652 [universeRegion checkEntity:sortedEntities[i]];
6655 if (![[
self gameController] isGamePaused])
6657 [universeRegion findCollisions];
6661 [universeRegion findShadowedEntities];
6665- (NSString*) collisionDescription
6667 if (universeRegion !=
nil)
return [universeRegion collisionDescription];
6672- (void) dumpCollisions
6674 dumpCollisionInfo = YES;
6680 return viewDirection;
6684- (void) setViewDirection:(
OOViewID) vd
6687 BOOL guiSelected = NO;
6689 if ((viewDirection == vd) && (vd != VIEW_CUSTOM) && (!displayGUI))
6695 ms =
DESC(
@"forward-view-string");
6699 ms =
DESC(
@"aft-view-string");
6703 ms =
DESC(
@"port-view-string");
6706 case VIEW_STARBOARD:
6707 ms =
DESC(
@"starboard-view-string");
6711 ms = [PLAYER customViewDescription];
6714 case VIEW_GUI_DISPLAY:
6715 [
self setDisplayText:YES];
6716 [
self setMainLightPosition:(Vector){ DEMO_LIGHT_POSITION }];
6727 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
6732 [[
self gameController] setMouseInteractionModeForFlight];
6735 if (viewDirection != vd || viewDirection == VIEW_CUSTOM)
6737 #if (ALLOW_CUSTOM_VIEWS_WHILE_PAUSED)
6738 BOOL gamePaused = [[
self gameController] isGamePaused];
6740 BOOL gamePaused = NO;
6745 if (ms && !gamePaused)
6747 [
self addMessage:ms forCount:3];
6749 else if (gamePaused)
6751 [message_gui clear];
6757- (void) enterGUIViewModeWithMouseInteraction:(BOOL)mouseInteraction
6759 [
self setViewDirection:VIEW_GUI_DISPLAY];
6760 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:mouseInteraction];
6764- (NSString *) soundNameForCustomSoundKey:(NSString *)key
6766 NSString *result =
nil;
6767 NSMutableSet *seen =
nil;
6768 id object = [customSounds objectForKey:key];
6770 if ([
object isKindOfClass:[NSArray
class]] && [
object count] > 0)
6772 key = [object oo_stringAtIndex:Ranrot() % [object count]];
6783 seen = [NSMutableSet set];
6785 if (
object ==
nil || ([result hasPrefix:
@"["] && [result hasSuffix:
@"]"]))
6789 [seen addObject:result];
6790 object = [customSounds objectForKey:result];
6791 if( [
object isKindOfClass:[NSArray
class]] && [
object count] > 0)
6793 result = [object oo_stringAtIndex:Ranrot() % [object count]];
6794 if ([key hasPrefix:
@"["] && [key hasSuffix:
@"]"]) key=result;
6798 if ([
object isKindOfClass:[NSString
class]])
6803 if (result ==
nil || ![result hasPrefix:
@"["] || ![result hasSuffix:
@"]"])
break;
6804 if ([seen containsObject:result])
6806 OOLogERR(
@"sound.customSounds.recursion",
@"recursion in customsounds.plist for '%@' (at '%@'), no sound will be played.", key, result);
6813 if (result ==
nil) result =
@"__oolite-no-sound";
6817 if ([result isEqualToString:
@"__oolite-no-sound"])
6819 OOLog(
@"sound.customSounds",
@"Could not resolve sound name in customsounds.plist for '%@', no sound will be played.", key);
6826- (NSDictionary *) screenTextureDescriptorForKey:(NSString *)key
6828 id value = [screenBackgrounds objectForKey:key];
6829 while ([value isKindOfClass:[NSArray
class]]) value = [value objectAtIndex:
Ranrot() % [value
count]];
6831 if ([value isKindOfClass:[NSString
class]]) value = [NSDictionary dictionaryWithObject:value forKey:
@"name"];
6832 else if (![value isKindOfClass:[NSDictionary
class]]) value =
nil;
6835 if (![[
self gui] preloadGUITexture:value]) value =
nil;
6841- (void) setScreenTextureDescriptorForKey:(NSString *)key descriptor:(NSDictionary *)desc
6843 NSMutableDictionary *sbCopy = [screenBackgrounds mutableCopy];
6846 [sbCopy removeObjectForKey:key];
6850 [sbCopy setObject:desc forKey:key];
6852 [screenBackgrounds release];
6853 screenBackgrounds = [sbCopy copy];
6858- (void) clearPreviousMessage
6860 if (currentMessage) [currentMessage release];
6861 currentMessage =
nil;
6865- (void) setMessageGuiBackgroundColor:(
OOColor *)some_color
6867 [message_gui setBackgroundColor:some_color];
6871- (void) displayMessage:(NSString *) text forCount:(
OOTimeDelta)count
6873 if (![currentMessage isEqual:text] || universal_time >= messageRepeatTime)
6875 if (currentMessage) [currentMessage release];
6876 currentMessage = [text retain];
6877 messageRepeatTime=universal_time + 6.0;
6878 [
self showGUIMessage:text withScroll:YES andColor:[message_gui textColor] overDuration:count];
6883- (void) displayCountdownMessage:(NSString *) text forCount:(
OOTimeDelta)count
6885 if (![currentMessage isEqual:text] && universal_time >= countdown_messageRepeatTime)
6887 if (currentMessage) [currentMessage release];
6888 currentMessage = [text retain];
6889 countdown_messageRepeatTime=universal_time +
count;
6890 [
self showGUIMessage:text withScroll:NO andColor:[message_gui textColor] overDuration:count];
6895- (void) addDelayedMessage:(NSString *)text forCount:(
OOTimeDelta)count afterDelay:(
double)delay
6897 NSMutableDictionary *msgDict = [NSMutableDictionary dictionaryWithCapacity:2];
6898 [msgDict setObject:text forKey:@"message"];
6899 [msgDict setObject:[NSNumber numberWithDouble:count] forKey:@"duration"];
6900 [
self performSelector:@selector(addDelayedMessage:) withObject:msgDict afterDelay:delay];
6904- (void) addDelayedMessage:(NSDictionary *) textdict
6906 NSString *msg =
nil;
6909 msg = [textdict oo_stringForKey:@"message"];
6910 if (msg ==
nil)
return;
6911 msg_duration = [textdict oo_nonNegativeDoubleForKey:@"duration" defaultValue:3.0];
6913 [
self addMessage:msg forCount:msg_duration];
6917- (void) addMessage:(NSString *)text forCount:(
OOTimeDelta)count
6919 [
self addMessage:text forCount:count forceDisplay:NO];
6923- (void) speakWithSubstitutions:(NSString *)text
6925#if OOLITE_SPEECH_SYNTH
6931 NSString *systemSaid =
nil;
6932 NSString *h_systemSaid =
nil;
6934 NSString *systemName = [
self getSystemName:systemID];
6936 systemSaid = systemName;
6938 NSString *h_systemName = [
self getSystemName:[player
targetSystemID]];
6939 h_systemSaid = h_systemName;
6941 NSString *spokenText = text;
6942 if (speechArray !=
nil)
6944 NSEnumerator *speechEnumerator =
nil;
6945 NSArray *thePair =
nil;
6947 for (speechEnumerator = [speechArray objectEnumerator]; (thePair = [speechEnumerator nextObject]); )
6949 NSString *original_phrase = [thePair oo_stringAtIndex:0];
6951 NSUInteger replacementIndex;
6953 replacementIndex = 1;
6955 replacementIndex = [thePair count] > 2 ? 2 : 1;
6958 NSString *replacement_phrase = [thePair oo_stringAtIndex:replacementIndex];
6959 if (![replacement_phrase isEqualToString:
@"_"])
6961 spokenText = [spokenText stringByReplacingOccurrencesOfString:original_phrase withString:replacement_phrase];
6964 spokenText = [spokenText stringByReplacingOccurrencesOfString:systemName withString:systemSaid];
6965 spokenText = [spokenText stringByReplacingOccurrencesOfString:h_systemName withString:h_systemSaid];
6967 [
self stopSpeaking];
6968 [
self startSpeakingString:spokenText];
6974- (void) addMessage:(NSString *) text forCount:(
OOTimeDelta) count forceDisplay:(BOOL) forceDisplay
6976 if (![currentMessage isEqual:text] || forceDisplay || universal_time >= messageRepeatTime)
6980 [
self speakWithSubstitutions:text];
6983 [
self showGUIMessage:text withScroll:YES andColor:[message_gui textColor] overDuration:count];
6985 [PLAYER doScriptEvent:OOJSID("consoleMessageReceived") withArgument:text];
6987 [currentMessage release];
6988 currentMessage = [text retain];
6989 messageRepeatTime=universal_time + 6.0;
6994- (void) addCommsMessage:(NSString *)text forCount:(
OOTimeDelta)count
6996 [
self addCommsMessage:text forCount:count andShowComms:_autoCommLog logOnly:NO];
7000- (void) addCommsMessage:(NSString *)text forCount:(
OOTimeDelta)count andShowComms:(BOOL)showComms logOnly:(BOOL)logOnly
7002 if ([
PLAYER showDemoShips])
return;
7004 NSString *expandedMessage =
OOExpand(text);
7006 if (![currentMessage isEqualToString:expandedMessage] || universal_time >= messageRepeatTime)
7015 NSString *format =
OOExpandKey(
@"speech-synthesis-incoming-message-@");
7016 [
self speakWithSubstitutions:[NSString stringWithFormat:format, expandedMessage]];
7019 [
self showGUIMessage:expandedMessage withScroll:YES andColor:[message_gui textCommsColor] overDuration:count];
7021 [currentMessage release];
7022 currentMessage = [expandedMessage retain];
7023 messageRepeatTime=universal_time + 6.0;
7026 [comm_log_gui printLongText:expandedMessage align:GUI_ALIGN_LEFT color:nil fadeTime:0.0 key:nil addToArray:[player
commLog]];
7028 if (showComms) [
self showCommsLog:6.0];
7035 [comm_log_gui setAlpha:1.0];
7036 if (![
self permanentCommLog]) [comm_log_gui fadeOutFromTime:[
self getTime] overDuration:how_long];
7040- (void) showGUIMessage:(NSString *)text withScroll:(BOOL)scroll andColor:(
OOColor *)selectedColor overDuration:(
OOTimeDelta)how_long
7044 [message_gui printLongText:text align:GUI_ALIGN_CENTER color:selectedColor fadeTime:how_long key:nil addToArray:nil];
7048 [message_gui printLineNoScroll:text align:GUI_ALIGN_CENTER color:selectedColor fadeTime:how_long key:nil addToArray:nil];
7050 [message_gui setAlpha:1.0f];
7054- (void) repopulateSystem
7061 [PLAYER doWorldScriptEvent:OOJSIDFromString(system_repopulator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
7069 volatile OOTimeDelta delta_t = inDeltaT * [
self timeAccelerationFactor];
7070 NSUInteger sessionID = _sessionID;
7071 OOLog(
@"universe.profile.update",
@"%@",
@"Begin update");
7074 next_repopulation -= delta_t;
7075 if (next_repopulation < 0)
7077 [
self repopulateSystem];
7080 unsigned i, ent_count = n_entities;
7081 Entity *my_entities[ent_count];
7083 [
self verifyEntitySessionIDs];
7086 for (i = 0; i < ent_count; i++)
7088 my_entities[i] = [sortedEntities[i] retain];
7091 NSString *
volatile update_stage =
@"initialisation";
7093 id volatile update_stage_param =
nil;
7100 skyClearColor[0] = 0.0;
7101 skyClearColor[1] = 0.0;
7102 skyClearColor[2] = 0.0;
7103 skyClearColor[3] = 0.0;
7105 time_delta = delta_t;
7106 universal_time += delta_t;
7108 if (
EXPECT_NOT([player showDemoShips] && [player guiScreen] == GUI_SCREEN_SHIPLIBRARY))
7110 update_stage =
@"demo management";
7112 if (universal_time >= demo_stage_time)
7124 [demo_ship setPosition:[demo_ship destination]];
7126 demo_stage_time = universal_time + 300.0;
7130 [demo_ship setVelocity:vel];
7132 demo_stage_time = universal_time + 0.25;
7136 [
self removeEntity:demo_ship];
7143 demo_ship_subindex = (demo_ship_subindex + 1) % [[demo_ships objectAtIndex:demo_ship_index] count];
7144 demo_ship = [
self newShipWithName:[[
self demoShipData] oo_stringForKey:kOODemoShipKey] usePlayerProxy:NO];
7146 if (demo_ship !=
nil)
7148 [demo_ship removeEquipmentItem:@"EQ_SHIELD_BOOSTER"];
7149 [demo_ship removeEquipmentItem:@"EQ_SHIELD_ENHANCER"];
7151 [demo_ship switchAITo:@"nullAI.plist"];
7152 [demo_ship setOrientation:q2];
7153 [demo_ship setScanClass: CLASS_NO_DRAW];
7154 [demo_ship setStatus: STATUS_COCKPIT_DISPLAY];
7155 [demo_ship setDemoShip: 1.0f];
7156 [demo_ship setDemoStartTime: universal_time];
7157 if ([
self addEntity:demo_ship])
7159 [demo_ship release];
7160 [demo_ship setStatus:STATUS_COCKPIT_DISPLAY];
7162 [demo_ship setPositionX:0.0f y:0.0f z:demo_start_z];
7163 [demo_ship setDestination: make_HPvector(0.0f, 0.0f, demo_start_z * 0.01f)];
7164 [demo_ship setVelocity:kZeroVector];
7165 [demo_ship setScanClass: CLASS_NO_DRAW];
7168 [
self setLibraryTextForDemoShip];
7171 demo_start_time=universal_time;
7186 [demo_ship setPositionX:0.0f y:[demo_ship destination].y * delta z:demo_start_z + ([demo_ship destination].z - demo_start_z) * delta ];
7190 update_stage =
@"update:entity";
7191 NSMutableSet *zombies =
nil;
7192 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7193 for (i = 0; i < ent_count; i++)
7195 Entity *thing = my_entities[i];
7197 update_stage_param = thing;
7198 update_stage =
@"update:entity [%@]";
7201 if (
EXPECT_NOT([thing status] == STATUS_DEAD && ![entitiesDeadThisUpdate containsObject:thing] && ![thing isPlayer]))
7203 if (zombies ==
nil) zombies = [NSMutableSet set];
7204 [zombies addObject:thing];
7216 update_stage =
@"update:list maintenance [%@]";
7223 while (index > 0 && z_distance < sortedEntities[index - 1]->zero_distance)
7225 sortedEntities[index] = sortedEntities[index - 1];
7226 sortedEntities[index - 1] = thing;
7228 sortedEntities[index]->zero_index = index;
7236 update_stage =
@"update:think [%@]";
7242 if ((universal_time > thinkTime)||(thinkTime == 0.0))
7251 update_stage_param =
nil;
7256 update_stage =
@"shootin' zombies";
7257 NSEnumerator *zombieEnum =
nil;
7259 for (zombieEnum = [zombies objectEnumerator]; (zombie = [zombieEnum nextObject]); )
7261 OOLogERR(
@"universe.zombie",
@"Found dead entity %@ in active entity list, removing. This is an internal error, please report it.", zombie);
7262 [
self removeEntity:zombie];
7267 update_stage =
@"updating linked lists";
7268 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7269 for (i = 0; i < ent_count; i++)
7276 update_stage =
@"collision and shadow detection";
7277 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7278 [
self filterSortedLists];
7279 [
self findCollisionsAndShadows];
7283 if (doLinkedListMaintenanceThisUpdate)
7286 doLinkedListMaintenanceThisUpdate = NO;
7289 @catch (NSException *exception)
7291 if ([[exception name] hasPrefix:
@"Oolite"])
7293 [
self handleOoliteException:exception];
7298 if (update_stage_param !=
nil) update_stage = [NSString stringWithFormat:update_stage, update_stage_param];
7300 OOLog(
kOOLogException,
@"***** Exception during [%@] in [Universe update:] : %@ : %@ *****", update_stage, [exception name], [exception reason]);
7306 update_stage =
@"clean up";
7307 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7308 for (i = 0; i < ent_count; i++)
7310 [my_entities[i] release];
7320 update_stage =
@"JS Garbage Collection";
7321 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7324 uint32 gcbytes1 = JS_GetGCParameter(JS_GetRuntime(context),JSGC_BYTES);
7330 uint32 gcbytes2 = JS_GetGCParameter(JS_GetRuntime(context),JSGC_BYTES);
7332 if (gcbytes2 < gcbytes1)
7334 OOLog(
@"universe.profile.jsgc",
@"Unplanned JS Garbage Collection from %d to %d",gcbytes1,gcbytes2);
7343 if ([
PLAYER status] == STATUS_DEAD) [PLAYER update:delta_t];
7346 [entitiesDeadThisUpdate autorelease];
7347 entitiesDeadThisUpdate =
nil;
7348 entitiesDeadThisUpdate = [[NSMutableSet alloc] initWithCapacity:n_entities];
7351 [
self prunePreloadingPlanetMaterials];
7354 OOLog(
@"universe.profile.update",
@"%@",
@"Update complete");
7359- (double) timeAccelerationFactor
7361 return timeAccelerationFactor;
7365- (void) setTimeAccelerationFactor:(
double)newTimeAccelerationFactor
7371 timeAccelerationFactor = newTimeAccelerationFactor;
7374- (double) timeAccelerationFactor
7380- (void) setTimeAccelerationFactor:(
double)newTimeAccelerationFactor
7386- (void) filterSortedLists
7396 Entity *e0, *next, *prev;
7397 OOHPScalar start, finish, next_start, next_finish, prev_start, prev_finish;
7420 start = e0->
position.z - 2.0f * e0->collision_radius;
7421 finish = start + 4.0f * e0->collision_radius;
7427 next_start = next->
position.z - 2.0f * next->collision_radius;
7428 if (next_start < finish)
7431 while ((next)&&(next_start < finish))
7434 next_finish = next_start + 4.0f * next->collision_radius;
7435 if (next_finish > finish)
7436 finish = next_finish;
7442 next_start = next->
position.z - 2.0f * next->collision_radius;
7464 start = e0->
position.z + 2.0f * e0->collision_radius;
7465 finish = start - 4.0f * e0->collision_radius;
7471 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7472 if (prev_start > finish)
7475 while ((prev)&&(prev_start > finish))
7478 prev_finish = prev_start - 4.0f * prev->collision_radius;
7479 if (prev_finish < finish)
7480 finish = prev_finish;
7486 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7510 start = e0->
position.y - 2.0f * e0->collision_radius;
7511 finish = start + 4.0f * e0->collision_radius;
7518 next_start = next->
position.y - 2.0f * next->collision_radius;
7519 if (next_start < finish)
7522 while ((next)&&(next_start < finish))
7525 next_finish = next_start + 4.0f * next->collision_radius;
7526 if (next_finish > finish)
7527 finish = next_finish;
7533 next_start = next->
position.y - 2.0f * next->collision_radius;
7555 start = e0->
position.y + 2.0f * e0->collision_radius;
7556 finish = start - 4.0f * e0->collision_radius;
7562 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7563 if (prev_start > finish)
7566 while ((prev)&&(prev_start > finish))
7569 prev_finish = prev_start - 4.0f * prev->collision_radius;
7570 if (prev_finish < finish)
7571 finish = prev_finish;
7577 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7601 start = e0->
position.x - 2.0f * e0->collision_radius;
7602 finish = start + 4.0f * e0->collision_radius;
7608 next_start = next->
position.x - 2.0f * next->collision_radius;
7609 if (next_start < finish)
7612 while ((next)&&(next_start < finish))
7615 next_finish = next_start + 4.0f * next->collision_radius;
7616 if (next_finish > finish)
7617 finish = next_finish;
7623 next_start = next->
position.x - 2.0f * next->collision_radius;
7645 start = e0->
position.x + 2.0f * e0->collision_radius;
7646 finish = start - 4.0f * e0->collision_radius;
7652 prev_start = prev->
position.x + 2.0f * prev->collision_radius;
7653 if (prev_start > finish)
7656 while ((prev)&&(prev_start > finish))
7659 prev_finish = prev_start - 4.0f * prev->collision_radius;
7660 if (prev_finish < finish)
7661 finish = prev_finish;
7667 prev_start = prev->
position.x + 2.0f * prev->collision_radius;
7691 start = e0->
position.y - 2.0f * e0->collision_radius;
7692 finish = start + 4.0f * e0->collision_radius;
7698 next_start = next->
position.y - 2.0f * next->collision_radius;
7699 if (next_start < finish)
7702 while ((next)&&(next_start < finish))
7705 next_finish = next_start + 4.0f * next->collision_radius;
7706 if (next_finish > finish)
7707 finish = next_finish;
7713 next_start = next->
position.y - 2.0f * next->collision_radius;
7734 start = e0->
position.y + 2.0f * e0->collision_radius;
7735 finish = start - 4.0f * e0->collision_radius;
7741 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7742 if (prev_start > finish)
7745 while ((prev)&&(prev_start > finish))
7748 prev_finish = prev_start - 4.0f * prev->collision_radius;
7749 if (prev_finish < finish)
7750 finish = prev_finish;
7756 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7780 start = e0->
position.z - 2.0f * e0->collision_radius;
7781 finish = start + 4.0f * e0->collision_radius;
7787 next_start = next->
position.z - 2.0f * next->collision_radius;
7788 if (next_start < finish)
7791 while ((next)&&(next_start < finish))
7796 next_finish = next_start + 4.0f * next->collision_radius;
7797 if (next_finish > finish)
7798 finish = next_finish;
7804 next_start = next->
position.z - 2.0f * next->collision_radius;
7826 start = e0->
position.z + 2.0f * e0->collision_radius;
7827 finish = start - 4.0f * e0->collision_radius;
7833 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7834 if (prev_start > finish)
7837 while ((prev)&&(prev_start > finish))
7862 OOLog(
@"general.error.inconsistentState",
@"Unexpected state in collision chain builder prev=%@, prev->c=%@, e0=%@, e0->c=%@",prev,prev->
collision_chain,e0,e0->
collision_chain);
7867 prev_finish = prev_start - 4.0f * prev->collision_radius;
7868 if (prev_finish < finish)
7869 finish = prev_finish;
7875 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7901 [
self setGalaxyTo:g andReinit:NO];
7905- (void) setGalaxyTo:(
OOGalaxyID) g andReinit:(BOOL) forced
7908 NSAutoreleasePool *pool =
nil;
7910 if (galaxyID != g || forced) {
7914 pool = [[NSAutoreleasePool alloc] init];
7916 for (i = 0; i < 256; i++)
7918 if (system_names[i])
7920 [system_names[i] release];
7922 system_names[i] = [[systemManager getProperty:@"name" forSystem:i inGalaxy:g] retain];
7932 NSDictionary *systemData;
7935 NSString *scriptName;
7942 systemData = [
self generateSystemData:targetSystemID];
7943 economy = [systemData oo_unsignedCharForKey:KEY_ECONOMY];
7944 scriptName = [systemData oo_stringForKey:@"market_script" defaultValue:nil];
7947 commodityMarket = [[commodities generateMarketForSystemWithEconomy:economy andScript:scriptName] retain];
7957- (NSDictionary *) descriptions
7959 if (_descriptions ==
nil)
7964 stringByAppendingPathComponent:@"Config"]
7965 stringByAppendingPathComponent:@"descriptions.plist"]];
7967 [
self verifyDescriptions];
7969 return _descriptions;
7973static void VerifyDesc(NSString *key,
id desc);
7978 if ([desc rangeOfString:
@"%n"].location != NSNotFound)
7980 OOLog(
@"descriptions.verify.percentN",
@"***** FATAL: descriptions.plist entry \"%@\
" contains the dangerous control sequence %%n.", key);
7989 foreach (subDesc, desc)
7991 VerifyDesc(key, subDesc);
7996static void VerifyDesc(NSString *key,
id desc)
7998 if ([desc isKindOfClass:[NSString
class]])
8000 VerifyDescString(key, desc);
8002 else if ([desc isKindOfClass:[NSArray
class]])
8004 VerifyDescArray(key, desc);
8006 else if ([desc isKindOfClass:[NSNumber
class]])
8012 OOLogERR(
@"descriptions.verify.badType",
@"***** FATAL: descriptions.plist entry for \"%@\
" is neither a string nor an array.", key);
8030 NSString *key =
nil;
8031 if (_descriptions ==
nil)
8033 OOLog(
@"descriptions.verify",
@"%@",
@"***** FATAL: Tried to verify descriptions, but descriptions was nil - unable to load any descriptions.plist file.");
8038 VerifyDesc(key, [_descriptions objectForKey:key]);
8045 [_descriptions autorelease];
8047 [
self verifyDescriptions];
8051- (NSDictionary *) explosionSetting:(NSString *)explosion
8053 return [explosionSettings oo_dictionaryForKey:explosion defaultValue:nil];
8057- (NSArray *) scenarios
8065 [_scenarios autorelease];
8070- (NSDictionary *) characters
8076- (NSDictionary *) missiontext
8082- (NSString *)descriptionForKey:(NSString *)key
8084 return [
self chooseStringForKey:key inDictionary:[
self descriptions]];
8088- (NSString *)descriptionForArrayKey:(NSString *)key index:(
unsigned)index
8090 NSArray *array = [[
self descriptions] oo_arrayForKey:key];
8091 if ([array
count] <= index)
return nil;
8092 return [array objectAtIndex:index];
8096- (BOOL) descriptionBooleanForKey:(NSString *)key
8098 return [[
self descriptions] oo_boolForKey:key];
8104 return systemManager;
8110 return [NSString stringWithFormat:@"%d %d", g, s];
8116 return [NSString stringWithFormat:@"interstellar: %d %d %d", g, s1, s2];
8120- (NSDictionary *) generateSystemData:(
OOSystemID) s
8122 return [
self generateSystemData:s useCache:YES];
8127- (NSDictionary *) generateSystemData:(
OOSystemID) s useCache:(BOOL) useCache
8134 NSString *systemKey = [NSString stringWithFormat:@"%u %u",[PLAYER galaxyNumber],s];
8136 return [systemManager getPropertiesForSystemKey:systemKey];
8142- (NSDictionary *) currentSystemData
8146 if (![
self inInterstellarSpace])
8148 return [
self generateSystemData:systemID];
8152 static NSDictionary *interstellarDict =
nil;
8153 if (interstellarDict ==
nil)
8155 NSString *interstellarName =
DESC(
@"interstellar-space");
8156 NSString *notApplicable =
DESC(
@"not-applicable");
8157 NSNumber *minusOne = [NSNumber numberWithInt:-1];
8158 NSNumber *zero = [NSNumber numberWithInt:0];
8159 interstellarDict = [[NSDictionary alloc] initWithObjectsAndKeys:
8160 interstellarName, KEY_NAME,
8161 minusOne, KEY_GOVERNMENT,
8162 minusOne, KEY_ECONOMY,
8163 minusOne, KEY_TECHLEVEL,
8164 zero, KEY_POPULATION,
8165 zero, KEY_PRODUCTIVITY,
8167 notApplicable, KEY_INHABITANTS,
8168 notApplicable, KEY_DESCRIPTION,
8172 return interstellarDict;
8179- (BOOL) inInterstellarSpace
8181 return [
self sun] ==
nil;
8189- (void) setSystemDataKey:(NSString *)key value:(NSObject *)object fromManifest:(NSString *)manifest
8191 [
self setSystemDataForGalaxy:galaxyID planet:systemID key:key value:object fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
8195- (void) setSystemDataForGalaxy:(
OOGalaxyID)gnum planet:(
OOSystemID)pnum key:(NSString *)key value:(
id)object fromManifest:(NSString *)manifest forLayer:(
OOSystemLayer)layer
8197 static BOOL sysdataLocked = NO;
8200 OOLogERR(
@"script.error",
@"%@",
@"System properties cannot be set during 'systemInformationChanged' events to avoid infinite loops.");
8204 BOOL sameGalaxy = (gnum == [PLAYER currentGalaxyID]);
8205 BOOL sameSystem = (sameGalaxy && pnum == [
self currentSystemID]);
8208 if ([key isEqualToString:
KEY_RADIUS] && sameGalaxy && sameSystem)
8210 OOLogERR(
@"script.error",
@"System property '%@' cannot be set while in the system.",key);
8214 if ([key isEqualToString:
@"coordinates"])
8216 OOLogERR(
@"script.error",
@"System property '%@' cannot be set.",key);
8221 NSString *overrideKey = [NSString stringWithFormat:@"%u %u", gnum, pnum];
8222 NSDictionary *sysInfo =
nil;
8225 [gui refreshStarChart];
8227 if (
object !=
nil) {
8229 if ([key isEqualToString:
KEY_NAME])
8231 object=(id)[[(NSString *)
object lowercaseString] capitalizedString];
8234 if (system_names[pnum]) [system_names[pnum] release];
8235 system_names[pnum] = [(NSString *)object retain];
8238 else if ([key isEqualToString:
@"sun_radius"])
8240 if ([
object doubleValue] < 1000.0 || [
object doubleValue] > 10000000.0 )
8242 object = ([object doubleValue] < 1000.0 ? (id)
@"1000.0" : (id)
@"10000000.0");
8245 else if ([key hasPrefix:
@"corona_"])
8247 object = (id)[NSString stringWithFormat:
@"%f",OOClamp_0_1_f([object floatValue])];
8251 [systemManager setProperty:key forSystemKey:overrideKey andLayer:layer toValue:object fromManifest:manifest];
8257 sysInfo = [systemManager getPropertiesForCurrentSystem];
8267 [[
self station] setEquivalentTechLevel:[object intValue]];
8268 [[
self station] setLocalShipyard:[
self shipsForSaleForSystem:systemID
8269 withTL:[object intValue] atTime:[PLAYER clockTime]]];
8272 else if ([key isEqualToString:
@"sun_color"] || [key isEqualToString:
@"star_count_multiplier"] ||
8273 [key isEqualToString:
@"nebula_count_multiplier"] || [key hasPrefix:
@"sky_"])
8278 for (i = n_entities - 1; i > 0; i--)
8279 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[SkyEntity class]]))
8280 the_sky = (
SkyEntity*)sortedEntities[i];
8286 if ([key isEqualToString:
@"sun_color"])
8295 for (i = n_entities - 1; i > 0; i--)
8296 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[DustEntity class]]))
8297 [(
DustEntity*)sortedEntities[i] setDustColor:[color blendedColorWithFraction:0.5 ofColor:[OOColor whiteColor]]];
8301 else if (the_sun !=
nil && ([key hasPrefix:
@"sun_"] || [key hasPrefix:
@"corona_"]))
8305 else if ([key isEqualToString:
@"texture"])
8307 [[
self planet] setUpPlanetFromTexture:(NSString *)object];
8309 else if ([key isEqualToString:
@"texture_hsb_color"])
8311 [[
self planet] setUpPlanetFromTexture: [[
self planet] textureFileName]];
8313 else if ([key isEqualToString:
@"air_color"])
8317 else if ([key isEqualToString:
@"illumination_color"])
8321 else if ([key isEqualToString:
@"air_color_mix_ratio"])
8323 [[
self planet] setAirColorMixRatio:[sysInfo oo_floatForKey:key]];
8327 sysdataLocked = YES;
8328 [PLAYER doScriptEvent:OOJSID("systemInformationChanged") withArguments:[NSArray arrayWithObjects:[NSNumber numberWithInt:gnum],[NSNumber numberWithInt:pnum],key,object,nil]];
8336 NSString *systemKey = [
self keyForPlanetOverridesForSystem:pnum inGalaxy:gnum];
8337 return [systemManager getPropertiesForSystemKey:systemKey];
8343 return [[
self generateSystemDataForGalaxy:gnum planet:pnum] allKeys];
8350 return [systemManager getProperty:key forSystem:pnum inGalaxy:gnum];
8356 return [
self getSystemName:sys forGalaxy:galaxyID];
8362 return [systemManager getProperty:@"name" forSystem:sys inGalaxy:gnum];
8368 return [[systemManager getProperty:@"government" forSystem:sys inGalaxy:galaxyID] unsignedCharValue];
8372- (NSString *) getSystemInhabitants:(
OOSystemID) sys
8374 return [
self getSystemInhabitants:sys plural:YES];
8378- (NSString *) getSystemInhabitants:(
OOSystemID) sys plural:(BOOL)plural
8380 NSString *ret =
nil;
8383 ret = [systemManager getProperty:KEY_INHABITANT forSystem:sys inGalaxy:galaxyID];
8391 return [systemManager getProperty:KEY_INHABITANTS forSystem:sys inGalaxy:galaxyID];
8396- (NSPoint) coordinatesForSystem:(
OOSystemID)s
8398 return [systemManager getCoordinatesForSystem:s inGalaxy:galaxyID];
8402- (
OOSystemID) findSystemFromName:(NSString *) sysName
8404 if (sysName ==
nil)
return -1;
8406 NSString *system_name =
nil;
8407 NSString *match = [sysName lowercaseString];
8409 for (i = 0; i < 256; i++)
8411 system_name = [system_names[i] lowercaseString];
8412 if ([system_name isEqualToString:match])
8423 OOLog(
@"deprecated.function",
@"%@",
@"findSystemAtCoords");
8424 return [
self findSystemNumberAtCoords:coords withGalaxy:g includingHidden:YES];
8428- (NSMutableArray *) nearbyDestinationsWithinRange:(
double)range
8430 NSMutableArray *result = [NSMutableArray arrayWithCapacity:16];
8433 NSPoint here = [PLAYER galaxy_coordinates];
8435 for (
unsigned short i = 0; i < 256; i++)
8437 NSPoint there = [
self coordinatesForSystem:i];
8439 if (dist <= range && (i != systemID || [
self inInterstellarSpace]))
8441 [result addObject: [NSDictionary dictionaryWithObjectsAndKeys:
8442 [NSNumber numberWithDouble:dist], @"distance",
8443 [NSNumber numberWithInt:i], @"sysID",
8444 [[
self generateSystemData:i] oo_stringForKey:@"sun_gone_nova" defaultValue:@"0"], @"nova",
8458 double min_dist = 10000.0;
8461 BOOL connected[256];
8462 for (i = 0; i < 256; i++)
8465 for (n = 0; n < 3; n++)
8467 for (i = 0; i < 256; i++)
8469 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8470 for (j = 0; j < 256; j++)
8472 NSPoint jpos = [systemManager getCoordinatesForSystem:j inGalaxy:g];
8476 connected[j] |= connected[i];
8477 connected[i] |= connected[j];
8483 for (i = 0; i < 256; i++)
8485 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8487 if ((connected[i])&&(distance < min_dist)&&(distance != 0.0))
8489 min_dist = distance;
8505 double min_dist = 10000.0;
8508 BOOL connected[256];
8509 for (i = 0; i < 256; i++)
8512 for (n = 0; n < 3; n++)
8514 for (i = 0; i < 256; i++)
8516 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8517 for (j = 0; j < 256; j++)
8519 NSPoint jpos = [systemManager getCoordinatesForSystem:j inGalaxy:g];
8523 connected[j] |= connected[i];
8524 connected[i] |= connected[j];
8530 for (i = 0; i < 256; i++)
8532 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8534 if ((connected[i])&&(distance < min_dist))
8536 min_dist = distance;
8545- (
OOSystemID) findSystemNumberAtCoords:(NSPoint) coords withGalaxy:(
OOGalaxyID)g includingHidden:(BOOL)hidden
8554 unsigned distance, dx, dy;
8556 unsigned min_dist = 10000;
8558 for (i = 0; i < 256; i++)
8561 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:g];
8562 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8568 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8569 dx =
ABS(coords.x - ipos.x);
8570 dy =
ABS(coords.y - ipos.y);
8572 if (dx > dy) distance = (dx + dx + dy) / 2;
8573 else distance = (dx + dy + dy) / 2;
8575 if (distance < min_dist)
8577 min_dist = distance;
8581 if ((distance == min_dist)&&(coords.y > ipos.y))
8586 else if ((distance == min_dist)&&(coords.y == ipos.y)&&(i==[
PLAYER targetSystemID]))
8595- (NSPoint) findSystemCoordinatesWithPrefix:(NSString *) p_fix
8597 return [
self findSystemCoordinatesWithPrefix:p_fix exactMatch:NO];
8601- (NSPoint) findSystemCoordinatesWithPrefix:(NSString *) p_fix exactMatch:(BOOL) exactMatch
8603 NSString *system_name =
nil;
8604 NSPoint system_coords = NSMakePoint(-1.0,-1.0);
8607 for (i = 0; i < 256; i++)
8609 system_found[i] = NO;
8610 system_name = [system_names[i] lowercaseString];
8611 if ((exactMatch && [system_name isEqualToString:p_fix]) || (!exactMatch && [system_name hasPrefix:p_fix]))
8614 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxyID];
8615 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8621 system_found[i] = YES;
8624 system_coords = [systemManager getCoordinatesForSystem:i inGalaxy:galaxyID];
8629 return system_coords;
8633- (BOOL*) systemsFound
8635 return (BOOL*)system_found;
8639- (NSString*)systemNameIndex:(
OOSystemID)index
8641 return system_names[index & 255];
8658 if (start == -1 || goal == -1)
return nil;
8660#ifdef CACHE_ROUTE_FROM_SYSTEM_RESULTS
8662 static NSDictionary *c_route =
nil;
8666 if (c_route !=
nil && c_start == start && c_goal == goal && c_optimizeBy == optimizeBy)
8675 if (start > 255 || goal > 255)
return nil;
8677 NSArray *neighbours[256];
8678 BOOL concealed[256];
8679 for (i = 0; i < 256; i++)
8681 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxyID];
8682 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8685 neighbours[i] = [NSArray array];
8690 neighbours[i] = [
self neighboursToSystem:i];
8697 double maxCost = optimizeBy ==
OPTIMIZED_BY_TIME ? 256 * (7 * 7) : 256 * (7 * 256 + 7);
8699 NSMutableArray *curr = [NSMutableArray arrayWithCapacity:256];
8702 NSMutableArray *next = [NSMutableArray arrayWithCapacity:256];
8703 while ([curr
count] != 0)
8705 for (i = 0; i < [curr count]; i++) {
8707 NSArray *ns = neighbours[[elemI
location]];
8708 for (j = 0; j < [ns count]; j++)
8718 NSPoint cpos = [systemManager getCoordinatesForSystem:c inGalaxy:galaxyID];
8719 NSPoint npos = [systemManager getCoordinatesForSystem:n inGalaxy:galaxyID];
8722 double lastTime = lastDistance * lastDistance;
8724 double distance = [ce
distance] + lastDistance;
8725 double time = [ce
time] + lastTime;
8727 int jumps = [ce
jumps] + 1;
8729 if (cost < maxCost && (cheapest[n] ==
nil || [cheapest[n] cost] > cost)) {
8734 if (n == goal && cost < maxCost)
8739 [curr setArray:next];
8740 [next removeAllObjects];
8744 if (!cheapest[goal])
return nil;
8746 NSMutableArray *route = [NSMutableArray arrayWithCapacity:256];
8750 [route insertObject:[NSNumber numberWithInt:[e
location]] atIndex:0];
8751 if ([e parent] == -1)
break;
8752 e = cheapest[[e
parent]];
8755#ifdef CACHE_ROUTE_FROM_SYSTEM_RESULTS
8758 c_optimizeBy = optimizeBy;
8760 c_route = [[NSDictionary alloc] initWithObjectsAndKeys: route, @"route", [NSNumber numberWithDouble:[cheapest[goal]
distance]], @"distance", nil];
8764 return [NSDictionary dictionaryWithObjectsAndKeys:
8766 [NSNumber numberWithDouble:[cheapest[goal]
distance]], @"distance",
8767 [NSNumber numberWithDouble:[cheapest[goal]
time]], @"time",
8768 [NSNumber numberWithInt:[cheapest[goal]
jumps]], @"jumps",
8774- (NSArray *) neighboursToSystem: (
OOSystemID) s
8776 if (s == systemID && closeSystems !=
nil)
8778 return closeSystems;
8780 NSArray *neighbours = [systemManager getNeighbourIDsForSystem:s inGalaxy:galaxyID];
8784 [closeSystems release];
8785 closeSystems = [neighbours copy];
8786 return closeSystems;
8820- (void) preloadPlanetTexturesForSystem:(
OOSystemID)s
8824 [
self prunePreloadingPlanetMaterials];
8826 if ([_preloadingPlanetMaterials
count] < 3)
8828 if (_preloadingPlanetMaterials ==
nil) _preloadingPlanetMaterials = [[NSMutableArray alloc] initWithCapacity:4];
8830 OOPlanetEntity *planet = [[OOPlanetEntity alloc] initAsMainPlanetForSystem:s];
8836 if (![surface isFinishedLoading])
8838 [_preloadingPlanetMaterials addObject:surface];
8842 OOMaterial *atmo = [planet atmosphereMaterial];
8843 if (atmo !=
nil) [_preloadingPlanetMaterials addObject:atmo];
8853- (NSDictionary *) globalSettings
8855 return globalSettings;
8859- (NSArray *) equipmentData
8861 return equipmentData;
8865- (NSArray *) equipmentDataOutfitting
8867 return equipmentDataOutfitting;
8873 return commodityMarket;
8877- (NSString *) timeDescription:(
double) interval
8879 double r_time = interval;
8880 NSString* result =
@"";
8884 int days = floor(r_time / 86400);
8885 r_time -= 86400 * days;
8886 result = [NSString stringWithFormat:@"%@ %d day%@", result, days, (days > 1) ? @"s" : @""];
8890 int hours = floor(r_time / 3600);
8891 r_time -= 3600 * hours;
8892 result = [NSString stringWithFormat:@"%@ %d hour%@", result, hours, (hours > 1) ? @"s" : @""];
8896 int mins = floor(r_time / 60);
8897 r_time -= 60 * mins;
8898 result = [NSString stringWithFormat:@"%@ %d minute%@", result, mins, (mins > 1) ? @"s" : @""];
8902 int secs = floor(r_time);
8903 result = [NSString stringWithFormat:@"%@ %d second%@", result, secs, (secs > 1) ? @"s" : @""];
8905 return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
8909- (NSString *) shortTimeDescription:(
double) interval
8911 double r_time = interval;
8912 NSString* result =
@"";
8915 if (interval <= 0.0)
8916 return DESC(
@"contracts-no-time");
8920 int days = floor(r_time / 86400);
8921 r_time -= 86400 * days;
8922 result = [NSString stringWithFormat:@"%@ %d %@", result, days, DESC_PLURAL(@"contracts-day-word", days)];
8927 int hours = floor(r_time / 3600);
8928 r_time -= 3600 * hours;
8929 result = [NSString stringWithFormat:@"%@ %d %@", result, hours, DESC_PLURAL(@"contracts-hour-word", hours)];
8932 if (parts < 2 && r_time > 60)
8934 int mins = floor(r_time / 60);
8935 r_time -= 60 * mins;
8936 result = [NSString stringWithFormat:@"%@ %d %@", result, mins, DESC_PLURAL(@"contracts-minute-word", mins)];
8939 if (parts < 2 && r_time > 0)
8941 int secs = floor(r_time);
8942 result = [NSString stringWithFormat:@"%@ %d %@", result, secs, DESC_PLURAL(@"contracts-second-word", secs)];
8944 return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
8948- (void) makeSunSkimmer:(
ShipEntity *) ship andSetAI:(BOOL)setAI
8950 if (setAI) [ship switchAITo:
@"oolite-traderAI.js"];
8954 if ([ship heatInsulation] < minInsulation) [ship setHeatInsulation:minInsulation];
8960 Random_Seed ret = [systemManager getRandomSeedForCurrentSystem];
8976- (void) loadStationMarkets:(NSArray *)marketData
8978 if (marketData ==
nil)
8983 NSArray *stations = [
self stations];
8985 NSDictionary *savedMarket =
nil;
8987 foreach (savedMarket, marketData)
8989 HPVector pos = [savedMarket oo_hpvectorForKey:@"position"];
8990 foreach (station, stations)
8993 if ([station allowsSaving] && station != [
UNIVERSE station])
8996 if (HPdistance2(pos,[station position]) < 1000000)
8998 [station setLocalMarket:[savedMarket oo_arrayForKey:@"market"]];
9008- (NSArray *) getStationMarkets
9010 NSMutableArray *markets = [[NSMutableArray alloc] init];
9011 NSArray *stations = [
self stations];
9014 NSMutableDictionary *savedMarket =
nil;
9018 foreach (station, stations)
9021 if ([station allowsSaving] && station != [
UNIVERSE station])
9023 stationMarket = [station localMarket];
9024 if (stationMarket !=
nil)
9026 savedMarket = [NSMutableDictionary dictionaryWithCapacity:2];
9028 [savedMarket setObject:ArrayFromHPVector([station position]) forKey:@"position"];
9029 [markets addObject:savedMarket];
9034 return [markets autorelease];
9043 NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionary];
9045 float tech_price_boost = (ship_seed.
a + ship_seed.b) / 256.0;
9051 for (i = 0; i < 256; i++)
9053 long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
9055 long long c_time = ship_seed.
a * 0x10000 + ship_seed.b * 0x100 + ship_seed.c;
9056 double ship_sold_time = reference_time + c_time;
9058 if (ship_sold_time < 0)
9059 ship_sold_time += 0x1000000;
9061 double days_until_sale = (ship_sold_time - current_time) / 86400.0;
9063 NSMutableArray *keysForShips = [NSMutableArray arrayWithArray:[registry
playerShipKeys]];
9065 for (si = 0; si < [keysForShips count]; si++)
9068 NSString *key = [keysForShips oo_stringAtIndex:si];
9070 NSArray *conditions = [dict oo_arrayForKey:@"conditions"];
9072 if (![player scriptTestConditions:conditions])
9074 [keysForShips removeObjectAtIndex:si--];
9076 NSString *condition_script = [dict oo_stringForKey:@"condition_script"];
9077 if (condition_script !=
nil)
9079 OOJSScript *condScript = [
self getConditionScript:condition_script];
9080 if (condScript !=
nil)
9084 JSBool allow_purchase;
9088 OK = [condScript
callMethod:OOJSID("allowOfferShip")
9093 if (OK) OK = JS_ValueToBoolean(context, result, &allow_purchase);
9097 if (OK && !allow_purchase)
9102 [keysForShips removeObjectAtIndex:si--];
9109 NSDictionary *systemInfo = [
self generateSystemData:s];
9111 if (specialTL != NSNotFound)
9114 techlevel = specialTL;
9119 techlevel = [systemInfo oo_unsignedIntForKey:KEY_TECHLEVEL];
9121 unsigned ship_index = (ship_seed.
d * 0x100 + ship_seed.e) % [keysForShips
count];
9122 NSString *ship_key = [keysForShips oo_stringAtIndex:ship_index];
9124 OOTechLevelID ship_techlevel = [ship_info oo_intForKey:KEY_TECHLEVEL];
9126 double chance = 1.0 - pow(1.0 - [ship_info oo_doubleForKey:KEY_CHANCE], MAX((
OOTechLevelID)1, techlevel - ship_techlevel));
9129 int superRand1 = ship_seed.
a * 0x10000 + ship_seed.c * 0x100 + ship_seed.e;
9130 uint32_t superRand2 = ship_seed.
b * 0x10000 + ship_seed.d * 0x100 + ship_seed.f;
9135 if ((days_until_sale > 0.0) && (days_until_sale < 30.0) && (ship_techlevel <= techlevel) && (
randf() < chance) && (shipBaseDict !=
nil))
9137 NSMutableDictionary* shipDict = [NSMutableDictionary dictionaryWithDictionary:shipBaseDict];
9138 NSMutableString* shortShipDescription = [NSMutableString stringWithCapacity:256];
9139 NSString *shipName = [shipDict oo_stringForKey:@"display_name" defaultValue:[shipDict oo_stringForKey:KEY_NAME]];
9142 NSMutableArray* extras = [NSMutableArray arrayWithArray:[[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
9143 NSString* fwdWeaponString = [[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9144 NSString* aftWeaponString = [[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON];
9146 NSMutableArray* options = [NSMutableArray arrayWithArray:[ship_info oo_arrayForKey:KEY_OPTIONAL_EQUIPMENT]];
9147 OOCargoQuantity maxCargo = [shipDict oo_unsignedIntForKey:@"max_cargo"];
9153 [shortShipDescription appendFormat:@"%@:", shipName];
9161 if (fwdWeapon && fwdWeaponString) [shipDict setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9162 if (aftWeapon && aftWeaponString) [shipDict setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
9164 int passengerBerthCount = 0;
9165 BOOL customised = NO;
9166 BOOL weaponCustomized = NO;
9168 NSString *fwdWeaponDesc =
nil;
9170 NSString *shortExtrasKey =
@"shipyard-first-extra";
9175 while ((
randf() < chance) && ([options
count]))
9178 int optionIndex =
Ranrot() % [options count];
9179 NSString *equipmentKey = [options oo_stringAtIndex:optionIndex];
9186 NSString *eqShortDesc = [item
name];
9188 if ([item techLevel] > techlevel)
9191 eqTechLevel =
MIN(eqTechLevel, 15U);
9194 if (
randf() * (eqTechLevel - techlevel) < 1.0)
9197 eqPrice *= (tech_price_boost + eqTechLevel - techlevel) * 90 / 100;
9203 if ([item incompatibleEquipment] !=
nil && extras !=
nil)
9205 NSEnumerator *keyEnum =
nil;
9207 BOOL incompatible = NO;
9209 for (keyEnum = [[item incompatibleEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9211 if ([extras containsObject:key])
9213 [options removeObject:equipmentKey];
9218 if (incompatible)
break;
9221 for (keyEnum = [[item incompatibleEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9223 if ([options containsObject:key])
9225 [options removeObject:key];
9232 if (condition_script !=
nil)
9234 OOJSScript *condScript = [
self getConditionScript:condition_script];
9235 if (condScript !=
nil)
9239 JSBool allow_addition;
9243 OK = [condScript
callMethod:OOJSID("allowAwardEquipment")
9248 if (OK) OK = JS_ValueToBoolean(JScontext, result, &allow_addition);
9252 if (OK && !allow_addition)
9263 if ([item requiresEquipment] !=
nil && extras !=
nil)
9265 NSEnumerator *keyEnum =
nil;
9269 for (keyEnum = [[item requiresEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9271 if (![extras containsObject:key])
9279 if ([item requiresAnyEquipment] !=
nil && extras !=
nil)
9281 NSEnumerator *keyEnum =
nil;
9285 for (keyEnum = [[item requiresAnyEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9287 if ([extras containsObject:key])
9297 if ([equipmentKey isEqualTo:
@"EQ_NAVAL_ENERGY_UNIT"])
9299 if ([extras containsObject:
@"EQ_ENERGY_UNIT"])
9301 [options removeObject:equipmentKey];
9306 if ([equipmentKey hasPrefix:
@"EQ_WEAPON"])
9310 if (availableFacings &
WEAPON_FACING_FORWARD && [new_weapon weaponThreatAssessment] > [fwdWeapon weaponThreatAssessment])
9313 price -= [
self getEquipmentPriceForKey:fwdWeaponString] * 90 / 1000;
9315 fwdWeaponString = equipmentKey;
9316 fwdWeapon = new_weapon;
9317 [shipDict setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9318 weaponCustomized = YES;
9319 fwdWeaponDesc = eqShortDesc;
9324 if (availableFacings &
WEAPON_FACING_AFT && (
isWeaponNone(aftWeapon) || [new_weapon weaponThreatAssessment] > [aftWeapon weaponThreatAssessment]))
9326 price -= [
self getEquipmentPriceForKey:aftWeaponString] * 90 / 1000;
9328 aftWeaponString = equipmentKey;
9329 aftWeapon = new_weapon;
9330 [shipDict setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
9334 [options removeObject:equipmentKey];
9341 if ([equipmentKey isEqualToString:
@"EQ_PASSENGER_BERTH"])
9347 [extras addObject:equipmentKey];
9348 passengerBerthCount++;
9354 [options removeObject:equipmentKey];
9360 [extras addObject:equipmentKey];
9361 if ([item isVisible])
9363 NSString *item = eqShortDesc;
9364 [shortShipDescription appendString:OOExpandKey(shortExtrasKey, item)];
9365 shortExtrasKey =
@"shipyard-additional-extra";
9368 [options removeObject:equipmentKey];
9374 [options removeObject:equipmentKey];
9379 BOOL lowercaseIgnore = [[
self descriptions] oo_boolForKey:@"lowercase_ignore"];
9381 if (passengerBerthCount)
9383 NSString* npb = (passengerBerthCount > 1)? [NSString stringWithFormat:
@"%d ", passengerBerthCount] : (id)
@"";
9384 NSString* ppb =
DESC_PLURAL(
@"passenger-berth", passengerBerthCount);
9385 NSString* extraPassengerBerthsDescription = [NSString stringWithFormat:DESC(@"extra-@-@-(passenger-berths)"), npb, ppb];
9386 NSString *item = extraPassengerBerthsDescription;
9387 [shortShipDescription appendString:OOExpandKey(shortExtrasKey, item)];
9388 shortExtrasKey =
@"shipyard-additional-extra";
9393 [shortShipDescription appendString:OOExpandKey(@"shipyard-standard-customer-model")];
9396 if (weaponCustomized)
9398 NSString *weapon = (lowercaseIgnore ? fwdWeaponDesc : [fwdWeaponDesc lowercaseString]);
9399 [shortShipDescription appendString:OOExpandKey(@"shipyard-forward-weapon-upgraded", weapon)];
9401 if (price > base_price)
9403 price = base_price +
cunningFee(price - base_price, 0.05);
9406 [shortShipDescription appendString:OOExpandKey(@"shipyard-price", price)];
9408 NSString *shipID = [NSString stringWithFormat:@"%06x-%06x", superRand1, superRand2];
9412 NSDictionary *ship_info_dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
9413 shipID, SHIPYARD_KEY_ID,
9414 ship_key, SHIPYARD_KEY_SHIPDATA_KEY,
9415 shipDict, SHIPYARD_KEY_SHIP,
9416 shortShipDescription, KEY_SHORT_DESCRIPTION,
9417 [NSNumber numberWithUnsignedLongLong:price], SHIPYARD_KEY_PRICE,
9418 extras, KEY_EQUIPMENT_EXTRAS,
9419 [NSNumber numberWithUnsignedShort:personality], SHIPYARD_KEY_PERSONALITY,
9422 [resultDictionary setObject:ship_info_dictionary forKey:shipID];
9432 NSMutableArray *resultArray = [[[resultDictionary allValues] mutableCopy] autorelease];
9433 [resultArray sortUsingFunction:compareName context:NULL];
9438 while (i < [resultArray
count])
9440 if (
compareName([resultArray objectAtIndex:i - 1], [resultArray objectAtIndex:i],
nil) == NSOrderedSame )
9442 [resultArray removeObjectAtIndex: i];
9452 return [NSArray arrayWithArray:resultArray];
9458 NSDictionary *ship1 = [(NSDictionary *)dict1 oo_dictionaryForKey:SHIPYARD_KEY_SHIP];
9459 NSDictionary *ship2 = [(NSDictionary *)dict2 oo_dictionaryForKey:SHIPYARD_KEY_SHIP];
9460 NSString *name1 = [ship1 oo_stringForKey:KEY_NAME];
9461 NSString *name2 = [ship2 oo_stringForKey:KEY_NAME];
9463 NSComparisonResult result = [[name1 lowercaseString] compare:[name2 lowercaseString]];
9464 if (result != NSOrderedSame)
9473 NSNumber *price1 = [(NSDictionary *)dict1 objectForKey:SHIPYARD_KEY_PRICE];
9474 NSNumber *price2 = [(NSDictionary *)dict2 objectForKey:SHIPYARD_KEY_PRICE];
9476 return [price1 compare:price2];
9484 NSString *ship_desc = [dict oo_stringForKey:@"ship_desc"];
9488 if (shipyard_info ==
nil)
9490 OOLogERR(
@"universe.tradeInValueForCommanderDictionary.valueCalculationError",
9491 @"Shipyard dictionary entry for ship %@ required for trade in value calculation, but does not exist. Setting ship value to 0.", ship_desc);
9495 base_price = [shipyard_info oo_unsignedLongLongForKey:SHIPYARD_KEY_PRICE defaultValue:0ULL];
9498 if(base_price == 0ULL)
return base_price;
9506 unsigned ship_missiles = [dict oo_unsignedIntForKey:@"missiles"];
9507 unsigned ship_max_passengers = [dict oo_unsignedIntForKey:@"max_passengers"];
9508 NSMutableArray *ship_extra_equipment = [NSMutableArray arrayWithArray:[[dict oo_dictionaryForKey:@"extra_equipment"] allKeys]];
9510 NSDictionary *basic_info = [shipyard_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT];
9511 unsigned base_missiles = [basic_info oo_unsignedIntForKey:KEY_EQUIPMENT_MISSILES];
9512 OOCreditsQuantity base_missiles_value = base_missiles * [UNIVERSE getEquipmentPriceForKey:@"EQ_MISSILE"] / 10;
9513 NSString *base_weapon_key = [basic_info oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9514 OOCreditsQuantity base_weapons_value = [UNIVERSE getEquipmentPriceForKey:base_weapon_key] / 10;
9515 NSMutableArray *base_extra_equipment = [NSMutableArray arrayWithArray:[basic_info oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
9516 NSString *weapon_key =
nil;
9519 base_weapon_key = [basic_info oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON defaultValue:nil];
9520 if (base_weapon_key !=
nil)
9521 base_weapons_value += [
UNIVERSE getEquipmentPriceForKey:base_weapon_key] / 10;
9528 NSArray *missileRoles = [dict oo_arrayForKey:@"missile_roles"];
9529 if (missileRoles !=
nil)
9532 for (i = 0; i < ship_missiles; i++)
9534 NSString *missile_desc = [missileRoles oo_stringAtIndex:i];
9535 if (missile_desc !=
nil && ![missile_desc isEqualToString:
@"NONE"])
9537 ship_missiles_value += [
UNIVERSE getEquipmentPriceForKey:missile_desc] / 10;
9542 ship_missiles_value = ship_missiles * [UNIVERSE getEquipmentPriceForKey:@"EQ_MISSILE"] / 10;
9545 long long extra_equipment_value = ship_max_passengers * [UNIVERSE getEquipmentPriceForKey:@"EQ_PASSENGER_BERTH"]/10;
9548 extra_equipment_value += ship_missiles_value - base_missiles_value;
9551 if (ship_fwd_weapon)
9554 ship_main_weapons_value = [UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9556 if (ship_aft_weapon)
9559 if (base_weapon_key !=
nil)
9561 ship_main_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9565 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9568 if (ship_port_weapon)
9571 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9573 if (ship_starboard_weapon)
9576 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9580 extra_equipment_value += ship_other_weapons_value;
9581 extra_equipment_value += ship_main_weapons_value - base_weapons_value;
9584 NSString *eq_key =
nil;
9588 for (i = [base_extra_equipment
count]-1; i > 0;i--)
9590 eq_key = [base_extra_equipment oo_stringAtIndex:i];
9591 if ([base_extra_equipment indexOfObject:eq_key inRange:NSMakeRange(0, i-1)] != NSNotFound)
9592 [base_extra_equipment removeObjectAtIndex:i];
9596 for (i = [base_extra_equipment
count]-1; i >= 0; i--)
9598 eq_key = [base_extra_equipment oo_stringAtIndex:i];
9599 if ([ship_extra_equipment containsObject:eq_key])
9600 [ship_extra_equipment removeObject:eq_key];
9602 extra_equipment_value -= ([
UNIVERSE getEquipmentPriceForKey:eq_key] / 10);
9608 for (i = [ship_extra_equipment
count]-1; i >= 0; i--)
9610 eq_key = [ship_extra_equipment oo_stringAtIndex:i];
9612 if ([item isPortableBetweenShips]) [ship_extra_equipment removeObjectAtIndex:i];
9616 for (i = [ship_extra_equipment
count]-1; i >= 0; i--)
9617 extra_equipment_value += ([
UNIVERSE getEquipmentPriceForKey:[ship_extra_equipment oo_stringAtIndex:i]] / 10);
9620 extra_equipment_value *= extra_equipment_value < 0 ? 1.4 : 0.9;
9624 if ((
long long)scrap_value > (
long long)base_price + extra_equipment_value)
return scrap_value;
9626 return base_price + extra_equipment_value;
9630- (NSString *) brochureDescriptionWithDictionary:(NSDictionary *)dict standardEquipment:(NSArray *)extras optionalEquipment:(NSArray *)options
9632 NSMutableArray *mut_extras = [NSMutableArray arrayWithArray:extras];
9633 NSString *allOptions = [options componentsJoinedByString:@" "];
9635 NSMutableString *desc = [NSMutableString stringWithFormat:@"The %@.", [dict oo_stringForKey: KEY_NAME]];
9641 OOCargoQuantity extra_cargo = [dict oo_unsignedIntForKey:@"extra_cargo" defaultValue:15];
9642 [desc appendFormat:@" Cargo capacity %dt", max_cargo];
9643 BOOL canExpand = ([allOptions rangeOfString:@"EQ_CARGO_BAY"].location != NSNotFound);
9645 [desc appendFormat:@" (expandable to %dt at most starports)", max_cargo + extra_cargo];
9646 [desc appendString:@"."];
9650 float top_speed = [dict oo_intForKey:@"max_flight_speed"];
9651 [desc appendFormat:@" Top speed %.3fLS.", 0.001 * top_speed];
9654 if ([mut_extras
count])
9656 unsigned n_berths = 0;
9658 for (i = 0; i < [mut_extras count]; i++)
9660 NSString* item_key = [mut_extras oo_stringAtIndex:i];
9661 if ([item_key isEqual:
@"EQ_PASSENGER_BERTH"])
9664 [mut_extras removeObjectAtIndex:i--];
9670 [desc appendString:@" Includes luxury accomodation for a single passenger."];
9672 [desc appendFormat:@" Includes luxury accomodation for %d passengers.", n_berths];
9677 if ([mut_extras
count])
9679 [desc appendString:@"\nComes with"];
9681 for (i = 0; i < [mut_extras count]; i++)
9683 NSString* item_key = [mut_extras oo_stringAtIndex:i];
9684 NSString* item_desc =
nil;
9685 for (j = 0; ((j < [equipmentData count])&&(!item_desc)) ; j++)
9687 NSString *eq_type = [[equipmentData oo_arrayAtIndex:j] oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
9688 if ([eq_type isEqual:item_key])
9693 switch ([mut_extras
count] - i)
9696 [desc appendFormat:@" %@ fitted as standard.", item_desc];
9699 [desc appendFormat:@" %@ and", item_desc];
9702 [desc appendFormat:@" %@,", item_desc];
9710 if ([options
count])
9712 [desc appendString:@"\nCan additionally be outfitted with"];
9714 for (i = 0; i < [options count]; i++)
9716 NSString* item_key = [options oo_stringAtIndex:i];
9717 NSString* item_desc =
nil;
9718 for (j = 0; ((j < [equipmentData count])&&(!item_desc)) ; j++)
9720 NSString *eq_type = [[equipmentData oo_arrayAtIndex:j] oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
9721 if ([eq_type isEqual:item_key])
9726 switch ([options
count] - i)
9729 [desc appendFormat:@" %@ at suitably equipped starports.", item_desc];
9732 [desc appendFormat:@" %@ and/or", item_desc];
9735 [desc appendFormat:@" %@,", item_desc];
9746- (HPVector) getWitchspaceExitPosition
9752- (Quaternion) getWitchspaceExitRotation
9755 Quaternion q_result;
9765 quaternion_normalize(&q_result);
9771- (HPVector) getSunSkimStartPositionForShip:(
ShipEntity*) ship
9787 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9788 if (v1.x||v1.y||v1.z)
9789 v1 = HPvector_normal(v1);
9793 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9794 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9800- (HPVector) getSunSkimEndPositionForShip:(
ShipEntity*) ship
9816 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9817 if (v1.x||v1.y||v1.z)
9818 v1 = HPvector_normal(v1);
9822 if (v2.x||v2.y||v2.z)
9823 v2 = HPvector_normal(v2);
9826 HPVector v3 = HPcross_product(v1, v2);
9827 if (v3.x||v3.y||v3.z)
9828 v3 = HPvector_normal(v3);
9832 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9833 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9834 v1.x += 15000 * v3.
x; v1.y += 15000 * v3.
y; v1.z += 15000 * v3.z;
9835 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9836 if (v1.x||v1.y||v1.z)
9837 v1 = HPvector_normal(v1);
9840 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9841 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9847- (NSArray *) listBeaconsWithCode:(NSString *)code
9849 NSMutableArray *result = [NSMutableArray array];
9850 Entity <OOBeaconEntity> *beacon = [
self firstBeacon];
9852 while (beacon !=
nil)
9854 NSString *beaconCode = [beacon beaconCode];
9855 if ([beaconCode rangeOfString:code options: NSCaseInsensitiveSearch].location != NSNotFound)
9857 [result addObject:beacon];
9859 beacon = [beacon nextBeacon];
9862 return [result sortedArrayUsingSelector:@selector(compareBeaconCodeWith:)];
9866- (void) allShipsDoScriptEvent:(jsid)event andReactToAIMessage:(NSString *)message
9869 int ent_count = n_entities;
9872 for (i = 0; i < ent_count; i++)
9874 if (sortedEntities[i]->isShip)
9880 for (i = 0; i < ship_count; i++)
9884 if (message !=
nil) [[se getAI] reactToMessage:message context:
@"global message"];
9899 return comm_log_gui;
9912 [message_gui clear];
9913 [comm_log_gui clear];
9914 [comm_log_gui printLongText:DESC(@"communications-log-string")
9915 align:GUI_ALIGN_CENTER color:[
OOColor yellowColor] fadeTime:0 key:nil addToArray:nil];
9919- (void) resetCommsLogColor
9925- (void) setDisplayText:(BOOL) value
9927 displayGUI = !!value;
9937- (void) setDisplayFPS:(BOOL) value
9939 displayFPS = !!value;
9949- (void) setAutoSave:(BOOL) value
9952 [[NSUserDefaults standardUserDefaults] setBool:autoSave forKey:@"autosave"];
9962- (void) setAutoSaveNow:(BOOL) value
9964 autoSaveNow = !!value;
9974- (void) setWireframeGraphics:(BOOL) value
9976 wireframeGraphics = !!value;
9977 [[NSUserDefaults standardUserDefaults] setBool:wireframeGraphics forKey:@"wireframe-graphics"];
9981- (BOOL) wireframeGraphics
9983 return wireframeGraphics;
9987- (BOOL) reducedDetail
10008 detailLevel = value;
10015 [
self setDetailLevelDirectly:value];
10016 [[NSUserDefaults standardUserDefaults] setInteger:detailLevel forKey:@"detailLevel"];
10019 if (old != detailLevel)
10029 return detailLevel;
10039- (void) handleOoliteException:(NSException *)exception
10041 if (exception !=
nil)
10046 [player
setStatus:STATUS_HANDLING_ERROR];
10048 OOLog(
kOOLogException,
@"***** Handling Fatal : %@ : %@ *****",[exception name], [exception reason]);
10049 NSString* exception_msg = [NSString stringWithFormat:@"Exception : %@ : %@ Please take a screenshot and/or press esc or Q to quit.", [exception name], [exception reason]];
10050 [
self addMessage:exception_msg forCount:30.0];
10051 [[
self gameController] setGamePaused:YES];
10055 OOLog(
kOOLogException,
@"***** Handling Non-fatal : %@ : %@ *****",[exception name], [exception reason]);
10061- (GLfloat)airResistanceFactor
10063 return airResistanceFactor;
10067- (void) setAirResistanceFactor:(GLfloat)newFactor
10069 airResistanceFactor = OOClamp_0_1_f(newFactor);
10076- (void) startSpeakingString:(NSString *) text
10078 [speechSynthesizer startSpeakingString:[NSString stringWithFormat:@"[[volm %.3f]]%@", 0.3333333f * [
OOSound masterVolume], text]];
10082- (void) stopSpeaking
10084 if ([speechSynthesizer respondsToSelector:
@selector(stopSpeakingAtBoundary:)])
10086 [speechSynthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary];
10090 [speechSynthesizer stopSpeaking];
10097 return [speechSynthesizer isSpeaking];
10102- (void) startSpeakingString:(NSString *) text
10104 NSData *utf8 = [text dataUsingEncoding:NSUTF8StringEncoding];
10108 const char *stringToSay = [text UTF8String];
10109 espeak_Synth(stringToSay, strlen(stringToSay) + 1 , 0, POS_CHARACTER, 0, espeakCHARS_UTF8 | espeakPHONEMES | espeakENDPAUSE, NULL, NULL);
10114- (void) stopSpeaking
10122 return espeak_IsPlaying();
10126- (NSString *) voiceName:(
unsigned int) index
10128 if (index >= espeak_voice_count)
10130 return [NSString stringWithCString: espeak_voices[index]->name];
10134- (
unsigned int) voiceNumber:(NSString *) name
10139 const char *
const label = [name UTF8String];
10143 unsigned int index = -1;
10144 while (espeak_voices[++index] && strcmp (espeak_voices[index]->name, label))
10146 return (index < espeak_voice_count) ? index : UINT_MAX;
10150- (
unsigned int) nextVoice:(
unsigned int) index
10152 if (++index >= espeak_voice_count)
10158- (
unsigned int) prevVoice:(
unsigned int) index
10160 if (--index >= espeak_voice_count)
10161 index = espeak_voice_count - 1;
10166- (
unsigned int) setVoice:(
unsigned int) index withGenderM:(BOOL) isMale
10168 if (index == UINT_MAX)
10169 index = [
self voiceNumber:DESC(@"espeak-default-voice")];
10171 if (index < espeak_voice_count)
10173 espeak_VOICE voice = { espeak_voices[index]->name, NULL, NULL, isMale ? 1 : 2 };
10174 espeak_SetVoiceByProperties (&voice);
10182- (void) startSpeakingString:(NSString *) text {}
10184- (void) stopSpeaking {}
10193- (BOOL) pauseMessageVisible
10195 return _pauseMessage;
10199- (void) setPauseMessageVisible:(BOOL)value
10201 _pauseMessage = value;
10205- (BOOL) permanentMessageLog
10207 return _permanentMessageLog;
10211- (void) setPermanentMessageLog:(BOOL)value
10213 _permanentMessageLog = value;
10217- (BOOL) autoMessageLogBg
10219 return _autoMessageLogBg;
10223- (void) setAutoMessageLogBg:(BOOL)value
10225 _autoMessageLogBg = !!value;
10229- (BOOL) permanentCommLog
10231 return _permanentCommLog;
10235- (void) setPermanentCommLog:(BOOL)value
10237 _permanentCommLog = value;
10241- (void) setAutoCommLog:(BOOL)value
10243 _autoCommLog = value;
10247- (BOOL) blockJSPlayerShipProps
10253- (void) setBlockJSPlayerShipProps:(BOOL)value
10266- (void) setUpSettings
10268 [
self resetBeacons];
10270 next_universal_id = 100;
10271 memset(entity_for_uid, 0,
sizeof entity_for_uid);
10273 [
self setMainLightPosition:kZeroVector];
10280 [message_gui autorelease];
10282 initWithPixelSize:NSMakeSize(480, 160)
10289 [comm_log_gui autorelease];
10291 initWithPixelSize:NSMakeSize(360, 120)
10302 [
self setTimeAccelerationFactor:TIME_ACCELERATION_FACTOR_DEFAULT];
10304 universal_time = 0.0;
10305 messageRepeatTime = 0.0;
10306 countdown_messageRepeatTime = 0.0;
10308#if OOLITE_SPEECH_SYNTH
10309 [speechArray autorelease];
10313 [commodities autorelease];
10317 [
self loadDescriptions];
10319 [characters autorelease];
10322 [customSounds autorelease];
10325 [globalSettings autorelease];
10329 [systemManager autorelease];
10332 [screenBackgrounds autorelease];
10336 [roleCategories autorelease];
10339 [autoAIMap autorelease];
10342 [equipmentData autorelease];
10343 [equipmentDataOutfitting autorelease];
10345 equipmentData = [[equipmentTemp sortedArrayUsingFunction:equipmentSort context:NULL] retain];
10346 equipmentDataOutfitting = [[equipmentTemp sortedArrayUsingFunction:equipmentSortOutfitting context:NULL] retain];
10350 [explosionSettings autorelease];
10358 NSMutableDictionary *tmp = [[NSMutableDictionary alloc] initWithCapacity:[commodities count]];
10360 foreach (type, [commodities goods])
10362 ShipEntity *container = [
self newShipWithRole:@"oolite-template-cargopod"];
10365 [tmp setObject:container forKey:type];
10366 [container release];
10368 [cargoPods release];
10369 cargoPods = [[NSDictionary alloc] initWithDictionary:tmp];
10376 NSMutableArray *badEntities =
nil;
10380 for (i = 0; i < n_entities; i++)
10382 entity = sortedEntities[i];
10383 if ([entity sessionID] != _sessionID)
10385 OOLogERR(
@"universe.sessionIDs.verify.failed",
@"Invalid entity %@ (came from session %lu, current session is %lu).", [entity shortDescription], [entity sessionID], _sessionID);
10386 if (badEntities ==
nil) badEntities = [NSMutableArray array];
10387 [badEntities addObject:entity];
10391 foreach (entity, badEntities)
10393 [
self removeEntity:entity];
10400- (BOOL) reinitAndShowDemo:(BOOL) showDemo
10404 assert(player !=
nil);
10415 [
self removeAllEntitiesExceptPlayer];
10428 [[
self gameController] setGamePaused:NO];
10429 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
10430 [PLAYER setSpeed:0.0];
10432 [
self loadDescriptions];
10433 [
self loadScenarios];
10435 [missiontext autorelease];
10441 [demo_ships release];
10443 demo_ship_index = 0;
10444 demo_ship_subindex = 0;
10447 breakPatternCounter = 0;
10450 cachedPlanet =
nil;
10451 cachedStation =
nil;
10453 [
self setUpSettings];
10458 [
self setUpCargoPods];
10460 if (![player setUpAndConfirmOK:YES])
10469 [
self addEntity:player];
10471 [[
self gameController] setPlayerFileToLoad:nil];
10473 [
self setUpInitialUniverse];
10476 [[
self station] initialiseLocalMarket];
10499 [
self populateNormalSpace];
10510 [
self verifyEntitySessionIDs];
10522 if (activeWormholes) [activeWormholes autorelease];
10523 activeWormholes = [[NSMutableArray arrayWithCapacity:16] retain];
10524 if (characterPool) [characterPool autorelease];
10525 characterPool = [[NSMutableArray arrayWithCapacity:256] retain];
10529 [
self setGalaxyTo: [player
galaxyNumber] andReinit:YES];
10541 [
self setDockingClearanceProtocolActive:
10542 [[
self currentSystemData] oo_boolForKey:@"stations_require_docking_clearance" defaultValue:YES]];
10544 [
self enterGUIViewModeWithMouseInteraction:NO];
10556- (Vector) randomPlaceWithinScannerFrom:(Vector)pos alongRoute:(Vector)route withOffset:(
double)offset
10558 pos.x +=
offset * route.
x + [
self randomDistanceWithinScanner];
10559 pos.y +=
offset * route.
y + [
self randomDistanceWithinScanner];
10560 pos.z +=
offset * route.z + [
self randomDistanceWithinScanner];
10566- (HPVector) fractionalPositionFrom:(HPVector)point0 to:(HPVector)point1 withFraction:(
double)routeFraction
10568 if (routeFraction == NSNotFound) routeFraction =
randf();
10570 point1 = OOHPVectorInterpolate(point0, point1, routeFraction);
10580- (BOOL)doRemoveEntity:(
Entity *)entity
10583 if ([entity canCollide])
10585 doLinkedListMaintenanceThisUpdate = YES;
10593 entity_for_uid[old_id] =
nil;
10603 if (sortedEntities[index] != entity)
10605 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity:%@ ENTITY IS NOT IN THE RIGHT PLACE IN THE ZERO_DISTANCE SORTED LIST -- FIXING...", entity);
10608 for (i = 0; (i < n_entities)&&(index == -1); i++)
10609 if (sortedEntities[i] == entity)
10612 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity:%@ ENTITY IS NOT IN THE ZERO_DISTANCE SORTED LIST -- CONTINUING...", entity);
10616 while ((
unsigned)index < n_entities)
10618 while (((
unsigned)index + n < n_entities)&&(sortedEntities[index + n] == entity))
10637 sortedEntities[index] = sortedEntities[index + n];
10638 if (sortedEntities[index])
10645 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity: REMOVED %d EXTRA COPIES OF %@ FROM THE ZERO_DISTANCE SORTED LIST", n - 1, entity);
10649 sortedEntities[n_entities] =
nil;
10656 if ([entities containsObject:entity])
10659 if ([entity isBreakPattern] && ![entity isVisualEffect])
10661 breakPatternCounter--;
10664 if ([entity isShip])
10667 [
self clearBeacon:se];
10669 if ([entity isWaypoint])
10672 [
self clearBeacon:wp];
10674 if ([entity isVisualEffect])
10677 [
self clearBeacon:ve];
10680 if ([entity isWormhole])
10682 [activeWormholes removeObject:entity];
10684 else if ([entity isPlanet])
10686 [allPlanets removeObject:entity];
10689 [entities removeObject:entity];
10697static void PreloadOneSound(NSString *soundName)
10699 if (![soundName hasPrefix:
@"["] && ![soundName hasSuffix:
@"]"])
10706- (void) preloadSounds
10709 NSString *key =
nil;
10712 id object = [customSounds objectForKey:key];
10713 if([
object isKindOfClass:[NSString
class]])
10715 PreloadOneSound(
object);
10717 else if([
object isKindOfClass:[NSArray
class]] && [
object count] > 0)
10719 NSString *soundName =
nil;
10720 foreach (soundName,
object)
10722 if ([soundName isKindOfClass:[NSString
class]])
10724 PreloadOneSound(soundName);
10731 PreloadOneSound(
@"afterburner1.ogg");
10737 NSAutoreleasePool *pool =
nil;
10739 while ([activeWormholes
count])
10741 pool = [[NSAutoreleasePool alloc] init];
10747 if (![whole isScanned] &&
10748 NSEqualPoints([
PLAYER galaxy_coordinates], [whole destinationCoordinates]) )
10753 [activeWormholes removeObjectAtIndex:0];
10755 @catch (NSException *exception)
10757 OOLog(
kOOLogException,
@"Squashing exception during wormhole unpickling (%@: %@).", [exception name], [exception reason]);
10764- (NSString *)chooseStringForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary
10766 id object = [dictionary objectForKey:key];
10767 if ([
object isKindOfClass:[NSString
class]])
return object;
10768 else if ([
object isKindOfClass:[NSArray
class]] && [
object count] > 0)
return [object oo_stringAtIndex:Ranrot() % [object count]];
10773#if OO_LOCALIZATION_TOOLS
10776- (void) dumpDebugGraphViz
10778 if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"universe-dump-debug-graphviz"])
10780 [
self dumpSystemDescriptionGraphViz];
10785- (void) dumpSystemDescriptionGraphViz
10787 NSMutableString *graphViz =
nil;
10788 NSArray *systemDescriptions =
nil;
10789 NSArray *thisDesc =
nil;
10790 NSUInteger i,
count, j, subCount;
10791 NSString *descLine =
nil;
10792 NSArray *curses =
nil;
10793 NSString *label =
nil;
10794 NSDictionary *keyMap =
nil;
10800 graphViz = [NSMutableString stringWithString:
10801 @"// System description grammar:\n\n"
10802 "digraph system_descriptions\n"
10804 "\tgraph [charset=\"UTF-8\", label=\"System description grammar\", labelloc=t, labeljust=l rankdir=LR compound=true nodesep=0.02 ranksep=1.5 concentrate=true fontname=Helvetica]\n"
10805 "\tedge [arrowhead=dot]\n"
10806 "\tnode [shape=none height=0.2 width=3 fontname=Helvetica]\n\t\n"];
10808 systemDescriptions = [[
self descriptions] oo_arrayForKey:@"system_description"];
10809 count = [systemDescriptions count];
10812 descLine =
DESC(
@"system-description-string");
10814 [graphViz appendFormat:@"\tsystem_description_string [label=\"%@\" shape=ellipse]\n", EscapedGraphVizString(label)];
10815 [
self addNumericRefsInString:descLine
10816 toGraphViz:graphViz
10817 fromNode:@"system_description_string"
10819 [graphViz appendString:@"\t\n"];
10822 [graphViz appendString:
10823 @"\tpercent_I [label=\"%I\\nInhabitants\" shape=diamond]\n"
10824 "\tpercent_H [label=\"%H\\nSystem name\" shape=diamond]\n"
10825 "\tpercent_RN [label=\"%R/%N\\nRandom name\" shape=diamond]\n"
10826 "\tpercent_J [label=\"%J\\nNumbered system name\" shape=diamond]\n"
10827 "\tpercent_G [label=\"%G\\nNumbered system name in chart number\" shape=diamond]\n\t\n"];
10830 [graphViz appendString:@"\tsubgraph cluster_thargoid_curses\n\t{\n\t\tlabel = \"Thargoid curses\"\n"];
10831 curses = [[
self descriptions] oo_arrayForKey:@"thargoid_curses"];
10832 subCount = [curses count];
10833 for (j = 0; j < subCount; ++j)
10836 [graphViz appendFormat:@"\t\tthargoid_curse_%lu [label=\"%@\"]\n", j, EscapedGraphVizString(label)];
10838 [graphViz appendString:@"\t}\n"];
10839 for (j = 0; j < subCount; ++j)
10841 [
self addNumericRefsInString:[curses oo_stringAtIndex:j]
10842 toGraphViz:graphViz
10843 fromNode:[NSString stringWithFormat:@"thargoid_curse_%lu", j]
10846 [graphViz appendString:@"\t\n"];
10850 for (i = 0; i <
count; ++i)
10853 label = [keyMap objectForKey:[NSString stringWithFormat:@"%lu", i]];
10854 if (label ==
nil) label = [NSString stringWithFormat:
@"[%lu]", i];
10855 else label = [NSString stringWithFormat:@"[%lu] (%@)", i, label];
10857 [graphViz appendFormat:@"\tsubgraph cluster_%lu\n\t{\n\t\tlabel=\"%@\"\n", i, EscapedGraphVizString(label)];
10859 thisDesc = [systemDescriptions oo_arrayAtIndex:i];
10860 subCount = [thisDesc count];
10861 for (j = 0; j < subCount; ++j)
10864 [graphViz appendFormat:@"\t\tn%lu_%lu [label=\"\\\"%@\\\"\"]\n", i, j, EscapedGraphVizString(label)];
10867 [graphViz appendString:@"\t}\n"];
10869 [graphViz appendString:@"\t\n"];
10872 for (i = 0; i !=
count; ++i)
10874 thisDesc = [systemDescriptions oo_arrayAtIndex:i];
10875 subCount = [thisDesc count];
10876 for (j = 0; j != subCount; ++j)
10878 descLine = [thisDesc oo_stringAtIndex:j];
10879 [
self addNumericRefsInString:descLine
10880 toGraphViz:graphViz
10881 fromNode:[NSString stringWithFormat:@"n%lu_%lu", i, j]
10887 [graphViz appendString:@"\t}\n"];
10893- (void) addNumericRefsInString:(NSString *)string toGraphViz:(NSMutableString *)graphViz fromNode:(NSString *)fromNode nodeCount:(NSUInteger)nodeCount
10895 NSString *index =
nil;
10896 NSInteger start, end;
10897 NSRange remaining, subRange;
10900 remaining = NSMakeRange(0, [
string length]);
10904 subRange = [string rangeOfString:@"[" options:NSLiteralSearch range:remaining];
10905 if (subRange.location == NSNotFound)
break;
10906 start = subRange.location + subRange.length;
10907 remaining.length -= start - remaining.location;
10908 remaining.location = start;
10910 subRange = [string rangeOfString:@"]" options:NSLiteralSearch range:remaining];
10911 if (subRange.location == NSNotFound)
break;
10912 end = subRange.location;
10913 remaining.length -= end - remaining.location;
10914 remaining.location = end;
10916 index = [string substringWithRange:NSMakeRange(start, end - start)];
10917 i = [index intValue];
10920 [graphViz appendFormat:@"\t%@ -> n%u_0 [color=\"%f,0.75,0.8\" lhead=cluster_%u]\n", fromNode, i, ((float)(i * 511 % nodeCount)) / ((float)nodeCount), i];
10923 if ([
string rangeOfString:
@"%I"].location != NSNotFound)
10925 [graphViz appendFormat:@"\t%@ -> percent_I [color=\"0,0,0.25\"]\n", fromNode];
10927 if ([
string rangeOfString:
@"%H"].location != NSNotFound)
10929 [graphViz appendFormat:@"\t%@ -> percent_H [color=\"0,0,0.45\"]\n", fromNode];
10931 if ([
string rangeOfString:
@"%R"].location != NSNotFound || [
string rangeOfString:
@"%N"].location != NSNotFound)
10933 [graphViz appendFormat:@"\t%@ -> percent_RN [color=\"0,0,0.65\"]\n", fromNode];
10937 if ([
string rangeOfString:
@"%J"].location != NSNotFound)
10939 [graphViz appendFormat:@"\t%@ -> percent_J [color=\"0,0,0.75\"]\n", fromNode];
10942 if ([
string rangeOfString:
@"%G"].location != NSNotFound)
10944 [graphViz appendFormat:@"\t%@ -> percent_G [color=\"0,0,0.85\"]\n", fromNode];
10952 NSArray *arguments =
nil;
10953 NSEnumerator *argEnum =
nil;
10954 NSString *arg =
nil;
10955 BOOL compileSysDesc = NO, exportSysDesc = NO, xml = NO;
10957 arguments = [[NSProcessInfo processInfo] arguments];
10959 for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
10961 if ([arg isEqual:
@"--compile-sysdesc"]) compileSysDesc = YES;
10962 else if ([arg isEqual:
@"--export-sysdesc"]) exportSysDesc = YES;
10963 else if ([arg isEqual:
@"--xml"]) xml = YES;
10964 else if ([arg isEqual:
@"--openstep"]) xml = NO;
10975- (void) prunePreloadingPlanetMaterials
10979 NSUInteger i = [_preloadingPlanetMaterials count];
10982 if ([[_preloadingPlanetMaterials objectAtIndex:i] isFinishedLoading])
10984 [_preloadingPlanetMaterials removeObjectAtIndex:i];
10992- (void) loadConditionScripts
10994 [conditionScripts autorelease];
10995 conditionScripts = [[NSMutableDictionary alloc] init];
11005- (void) addConditionScripts:(NSEnumerator *)scripts
11007 NSString *scriptname =
nil;
11008 while ((scriptname = [scripts nextObject]))
11010 if ([conditionScripts objectForKey:scriptname] ==
nil)
11015 [conditionScripts setObject:script forKey:scriptname];
11022- (
OOJSScript*) getConditionScript:(NSString *)scriptname
11024 return [conditionScripts objectForKey:scriptname];
11030@implementation OOSound (OOCustomSounds)
11032+ (id) soundWithCustomSoundKey:(NSString *)key
11034 NSString *fileName = [UNIVERSE soundNameForCustomSoundKey:key];
11035 if (fileName ==
nil)
return nil;
11040- (id) initWithCustomSoundKey:(NSString *)key
11049@implementation OOSoundSource (OOCustomSounds)
11051+ (id) sourceWithCustomSoundKey:(NSString *)key
11053 return [[[
self alloc] initWithCustomSoundKey:key] autorelease];
11057- (id) initWithCustomSoundKey:(NSString *)key
11060 if (theSound !=
nil)
11062 self = [
self initWithSound:theSound];
11073- (void) playCustomSoundWithKey:(NSString *)key
11076 if (theSound !=
nil) [
self playSound:theSound];
11083 NSDictionary *one = (NSDictionary *)a;
11084 NSDictionary *two = (NSDictionary *)b;
11085 int pri_one = [one oo_intForKey:@"priority" defaultValue:100];
11086 int pri_two = [two oo_intForKey:@"priority" defaultValue:100];
11087 if (pri_one < pri_two)
return NSOrderedAscending;
11088 if (pri_one > pri_two)
return NSOrderedDescending;
11089 return NSOrderedSame;
11095 NSArray *one = (NSArray *)a;
11096 NSArray *two = (NSArray *)b;
11100 OOCreditsQuantity comp1 = [[one oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000];
11101 OOCreditsQuantity comp2 = [[two oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000];
11102 if (comp1 < comp2)
return NSOrderedAscending;
11103 if (comp1 > comp2)
return NSOrderedDescending;
11105 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11106 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11107 if (comp1 < comp2)
return NSOrderedAscending;
11108 if (comp1 > comp2)
return NSOrderedDescending;
11110 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11111 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11112 if (comp1 < comp2)
return NSOrderedAscending;
11113 if (comp1 > comp2)
return NSOrderedDescending;
11115 return NSOrderedSame;
11121 NSArray *one = (NSArray *)a;
11122 NSArray *two = (NSArray *)b;
11126 OOCreditsQuantity comp1 = [[one oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"purchase_sort_order" defaultValue:[[one oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000]];
11127 OOCreditsQuantity comp2 = [[two oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"purchase_sort_order" defaultValue:[[two oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000]];
11128 if (comp1 < comp2)
return NSOrderedAscending;
11129 if (comp1 > comp2)
return NSOrderedDescending;
11131 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11132 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11133 if (comp1 < comp2)
return NSOrderedAscending;
11134 if (comp1 > comp2)
return NSOrderedDescending;
11136 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11137 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11138 if (comp1 < comp2)
return NSOrderedAscending;
11139 if (comp1 > comp2)
return NSOrderedDescending;
11141 return NSOrderedSame;
11147 NSString *result = [UNIVERSE descriptionForKey:key];
11148 if (result ==
nil) result = key;
11156 NSArray *conditions = [[UNIVERSE descriptions] oo_arrayForKey:@"plural-rules"];
11159 NSString *tmp = [UNIVERSE descriptionForKey:key];
11162 static NSMutableSet *warned =
nil;
11164 if (![warned containsObject:tmp])
11166 OOLogWARN(
@"localization.plurals",
@"'%@' found in descriptions.plist, should be '%@%%0'. Localization data needs updating.",key,key);
11167 if (warned ==
nil) warned = [[NSMutableSet alloc] init];
11168 [warned addObject:tmp];
11172 if (conditions ==
nil)
11182 for (index = i = 0; i < [conditions count]; ++index, ++i)
11184 const char *cond = [[conditions oo_stringAtIndex:i] UTF8String];
11188 long int input =
count;
11191 while (isspace (*cond))
11196 while (isspace (*cond))
11199 char command = *cond++;
11211 long int param = strtol(cond, (
char **)&cond, 10);
11226 if (flag ^ (input == param))
11230 if (flag ^ (input != param))
11235 if (flag ^ (input < param))
11239 if (flag ^ (input > param))
#define INTERMEDIATE_CLEAR_DEPTH
#define SCANNER_MAX_RANGE
#define SCANNER_MAX_RANGE2
#define OO_DEBUG_POP_PROGRESS()
#define OO_DEBUG_PROGRESS(...)
#define OO_DEBUG_PUSH_PROGRESS(...)
OOGUITabStop OOGUITabSettings[GUI_MAX_COLUMNS]
#define MAIN_GUI_PIXEL_WIDTH
#define MAIN_GUI_PIXEL_HEIGHT
NSRect OORectFromString(NSString *text, GLfloat x, GLfloat y, NSSize siz)
void OODrawString(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
@ kOOBreakPatternMaxSides
#define BREAK_PATTERN_RING_SPEED
#define BREAK_PATTERN_RING_SPACING
NSInteger OOComparisonResult
#define foreachkey(VAR, DICT)
NSString * OOStringFromGraphicsDetail(OOGraphicsDetail detail)
void CompileSystemDescriptions(BOOL asXML)
void ExportSystemDescriptions(BOOL asXML)
NSString * OOStringifySystemDescriptionLine(NSString *line, NSDictionary *indicesToKeys, BOOL useFallback)
void OOStandardsDeprecated(NSString *message)
BOOL OOEnforceStandards(void)
void OOInitDebugSupport(void)
BOOL IsShipPredicate(Entity *entity, void *parameter)
BOOL IsVisualEffectPredicate(Entity *entity, void *parameter)
BOOL YESPredicate(Entity *entity, void *parameter)
HPVector OOHPVectorRandomRadial(OOHPScalar maxLength)
HPVector OOProjectHPVectorToPlane(HPVector point, HPVector plane, HPVector normal)
HPVector OORandomPositionInShell(HPVector centre, OOHPScalar inner, OOHPScalar outer)
const HPVector kZeroHPVector
HPVector OOHPVectorRandomSpatial(OOHPScalar maxLength)
const HPVector kBasisZHPVector
HPVector OORandomPositionInCylinder(HPVector centre1, OOHPScalar exclusion1, HPVector centre2, OOHPScalar exclusion2, OOHPScalar radius)
#define OOJS_PROFILE_EXIT
#define OOJS_PROFILE_ENTER
void OOJSPauseTimeLimiter(void)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
OOINLINE JSContext * OOJSAcquireContext(void)
OOINLINE void OOJSRelinquishContext(JSContext *context)
void OOJSResumeTimeLimiter(void)
#define OOLogWARN(class, format,...)
#define OOLogERR(class, format,...)
NSString *const kOOLogException
NSString *const kOOLogInconsistentState
BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass)
#define OOLogOutdentIf(class)
#define OOLog(class, format,...)
NSString *const kOOLogParameterError
#define OOLogIndentIf(class)
OOMatrix OOMatrixMultiply(OOMatrix a, OOMatrix b)
const OOMatrix kIdentityMatrix
Vector OOVectorMultiplyMatrix(Vector v, OOMatrix m)
@ MOUSE_MODE_UI_SCREEN_WITH_INTERACTION
void OOGLLoadModelView(OOMatrix matrix)
void OOGLLookAt(Vector eye, Vector center, Vector up)
OOMatrix OOGLGetModelView(void)
void OOGLPushModelView(void)
void OOGLResetModelView(void)
void OOGLTranslateModelView(Vector vector)
void OOGLFrustum(double left, double right, double bottom, double top, double near, double far)
void OOGLMultModelView(OOMatrix matrix)
OOMatrix OOGLGetModelViewProjection(void)
OOMatrix OOGLPopModelView(void)
void OOGLResetProjection(void)
#define OOVerifyOpenGLState()
BOOL OOCheckOpenGLErrors(NSString *format,...)
void GLScaledLineWidth(GLfloat width)
#define OOSetOpenGLState(STATE)
Vector vector_forward_from_quaternion(Quaternion quat)
void basis_vectors_from_quaternion(Quaternion quat, Vector *outRight, Vector *outUp, Vector *outForward)
void quaternion_set_random(Quaternion *quat)
const Quaternion kIdentityQuaternion
Quaternion quaternion_rotation_between(Vector v0, Vector v1)
void quaternion_rotate_about_y(Quaternion *quat, OOScalar angle)
void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, OOScalar angle)
NSString * OOShipLibraryCategorySingular(NSString *category)
NSString * OOShipLibraryWitchspace(ShipEntity *demo_ship)
NSString * OOShipLibraryTurrets(ShipEntity *demo_ship)
NSString * OOShipLibraryShields(ShipEntity *demo_ship)
NSString * OOShipLibraryCargo(ShipEntity *demo_ship)
NSString * OOShipLibraryCategoryPlural(NSString *category)
static NSString *const kOODemoShipClass
NSString * OOShipLibraryGenerator(ShipEntity *demo_ship)
static NSString *const kOODemoShipShipData
NSString * OOShipLibrarySize(ShipEntity *demo_ship)
NSString * OOShipLibrarySpeed(ShipEntity *demo_ship)
static NSString *const kOODemoShipKey
NSString * OOShipLibraryWeapons(ShipEntity *demo_ship)
NSString * OOShipLibraryTurnRate(ShipEntity *demo_ship)
#define OOExpandKey(key,...)
#define OOExpand(string,...)
NSMutableArray * ScanTokensFromString(NSString *values)
@ OO_SYSTEMCONCEALMENT_NOTHING
@ OO_SYSTEMCONCEALMENT_NONAME
uint8_t OOWeaponFacingSet
NSString * OOCommodityType
uint64_t OOCreditsQuantity
#define VALID_WEAPON_FACINGS
@ WEAPON_FACING_STARBOARD
const Vector kBasisYVector
const Vector kBasisZVector
const Vector kBasisXVector
BOOL isWeaponNone(OOWeaponType weapon)
#define ENTITY_PERSONALITY_MAX
NSString * OOEquipmentIdentifierFromWeaponType(OOWeaponType weapon) CONST_FUNC
OOWeaponType OOWeaponTypeFromEquipmentIdentifierSloppy(NSString *string) PURE_FUNC
#define ShipScriptEvent(context, ship, event,...)
#define SUN_SKIM_RADIUS_FACTOR
#define TIME_ACCELERATION_FACTOR_DEFAULT
#define PASSENGER_BERTH_SPACE
#define MIN_DISTANCE_TO_BUOY
#define DEMO_LIGHT_POSITION
#define DESC_PLURAL(key, count)
#define OOLITE_EXCEPTION_FATAL
@ EQUIPMENT_SHORT_DESC_INDEX
#define TIME_ACCELERATION_FACTOR_MAX
NSString * OOLookUpDescriptionPRIV(NSString *key)
#define SAFE_ADDITION_FACTOR2
@ OO_POSTFX_COLORBLINDNESS_TRITAN
NSString * OOLookUpPluralDescriptionPRIV(NSString *key, NSInteger count)
NSComparisonResult populatorPrioritySort(id a, id b, void *context)
NSComparisonResult equipmentSortOutfitting(id a, id b, void *context)
NSComparisonResult equipmentSort(id a, id b, void *context)
#define SYSTEM_REPOPULATION_INTERVAL
#define OOLITE_EXCEPTION_DATA_NOT_FOUND
BOOL(* EntityFilterPredicate)(Entity *entity, void *parameter)
#define DOCKED_ILLUM_LEVEL
const GLfloat framebufferQuadVertices[]
static const OOMatrix fwd_matrix
#define SKY_AMBIENT_ADJUSTMENT
static GLfloat docked_light_specular[4]
static NSString *const kOOLogUniversePopulateWitchspace
static const OOMatrix port_matrix
Universe * gSharedUniverse
static const OOMatrix starboard_matrix
#define SUN_AMBIENT_INFLUENCE
static BOOL MaintainLinkedLists(Universe *uni)
static OOComparisonResult compareName(id dict1, id dict2, void *context)
static BOOL demo_light_on
static const OOMatrix aft_matrix
static NSString *const kOOLogEntityVerificationRebuild
static BOOL object_light_on
Entity * gOOJSPlayerIfStale
static GLfloat docked_light_ambient[4]
#define DEMO2_FLY_IN_STAGE_TIME
static NSString *const kOOLogEntityVerificationError
static GLfloat sun_off[4]
static NSString *const kOOLogUniversePopulateError
#define DEMO2_VANISHING_DISTANCE
const GLuint framebufferQuadIndices[]
static GLfloat docked_light_diffuse[4]
static GLfloat demo_light_position[4]
#define DOCKED_AMBIENT_LEVEL
OOINLINE BOOL EntityInRange(HPVector p1, Entity *e2, float range)
static OOComparisonResult comparePrice(id dict1, id dict2, void *context)
NSDictionary * demoShipData()
void deleteOpenGLObjects()
void drawTargetTextureIntoDefaultFramebuffer()
void verifyEntitySessionIDs()
void setLibraryTextForDemoShip()
void prepareToRenderIntoDefaultFramebuffer()
void verifyDescriptions()
void setUpInitialUniverse()
float randomDistanceWithinScanner()
void populateSpaceFromActiveWormholes()
void setGuiToIntroFirstGo:(BOOL justCobra)
void runLocalizationTools()
void setNextThinkTime:(OOTimeAbsolute ntt)
void setOwner:(ShipEntity *ship)
OOTimeDelta thinkTimeInterval
void setState:(NSString *stateName)
OOTimeAbsolute nextThinkTime
unsigned isImmuneToBreakPatternHide
void setAtmosphereFogging:(OOColor *fogging)
void removeFromLinkedLists()
void drawImmediate:translucent:(bool immediate,[translucent] bool translucent)
void setUniversalID:(OOUniversalID uid)
OOUniversalID universalID
void setThrowSparks:(BOOL value)
void setVelocity:(Vector vel)
void updateCameraRelativePosition()
void setOrientation:(Quaternion quat)
void update:(OOTimeDelta delta_t)
unsigned collisionTestFilter
GLfloat collisionRadius()
void wasRemovedFromUniverse()
void setScanClass:(OOScanClass sClass)
void setPositionX:y:z:(OOHPScalar x,[y] OOHPScalar y,[z] OOHPScalar z)
HPVector absolutePositionForSubentityOffset:(HPVector offset)
void setEnergy:(GLfloat amount)
Quaternion normalOrientation()
ShipEntity * parentEntity()
unsigned isExplicitlyNotMainStation
void setStatus:(OOEntityStatus stat)
void setPosition:(HPVector posn)
GameController * sharedController()
void logProgress:(NSString *message)
void setLineWidth:(GLfloat value)
NSString * deferredHudName
void setOverallAlpha:(GLfloat newAlphaValue)
void setFov:fromFraction:(float value,[fromFraction] BOOL fromFraction)
void setGammaValue:(float value)
void setMsaa:(BOOL newMsaa)
void completePendingTasks()
OOAsyncWorkManager * sharedAsyncWorkManager()
void setInnerColor:outerColor:(OOColor *color1,[outerColor] OOColor *color2)
void setLifetime:(double lifetime)
instancetype breakPatternWithPolygonSides:startAngle:aspectRatio:(NSUInteger sides,[startAngle] float startAngleDegrees,[aspectRatio] float aspectRatio)
void setObject:forKey:inCache:(id inElement,[forKey] NSString *inKey,[inCache] NSString *inCacheKey)
id objectForKey:inCache:(NSString *inKey,[inCache] NSString *inCacheKey)
OOCacheManager * sharedCache()
OOCharacter * randomCharacterWithRole:andOriginalSystem:(NSString *c_role,[andOriginalSystem] OOSystemID s)
OOColor * colorWithRed:green:blue:alpha:(float red,[green] float green,[blue] float blue,[alpha] float alpha)
OOColor * brightColorWithDescription:(id description)
OOColor * colorWithDescription:(id description)
OOColor * colorWithHue:saturation:brightness:alpha:(float hue,[saturation] float saturation,[brightness] float brightness,[alpha] float alpha)
OOColor * blendedColorWithFraction:ofColor:(float fraction,[ofColor] OOColor *color)
NSArray * saveStationAmounts()
NSString * conditionScript()
OOTechLevelID techLevel()
OOEquipmentType * equipmentTypeWithIdentifier:(NSString *identifier)
OOCreditsQuantity price()
instancetype explosionCloudFromEntity:withSettings:(Entity *entity,[withSettings] NSDictionary *settings)
instancetype laserFlashWithPosition:velocity:color:(HPVector position,[velocity] Vector vel,[color] OOColor *color)
void resetGraphicsState()
OOGraphicsResetManager * sharedManager()
void runCallback:(HPVector location)
BOOL callMethod:inContext:withArguments:count:result:(jsid methodID,[inContext] JSContext *context,[withArguments] jsval *argv,[count] intN argc,[result] jsval *outResult)
OOJavaScriptEngine * sharedEngine()
void garbageCollectionOpportunity:(BOOL force)
void removeObject:(id object)
OOOpenGLExtensionManager * sharedManager()
OOGraphicsDetail defaultDetailLevel()
instancetype shrinkingRingFromEntity:(Entity *sourceEntity)
instancetype ringFromEntity:(Entity *sourceEntity)
id jsScriptFromFileNamed:properties:(NSString *fileName,[properties] NSDictionary *properties)
instancetype groupWithName:(NSString *name)
NSDictionary * shipyardInfoForKey:(NSString *key)
NSArray * playerShipKeys()
NSString * randomShipKeyForRole:(NSString *role)
OOShipRegistry * sharedRegistry()
NSDictionary * shipInfoForKey:(NSString *key)
NSDictionary * effectInfoForKey:(NSString *key)
id soundWithCustomSoundKey:(NSString *key)
void setRadius:andCorona:(GLfloat rad,[andCorona] GLfloat corona)
BOOL changeSunProperty:withDictionary:(NSString *key,[withDictionary] NSDictionary *dict)
void setPosition:(HPVector posn)
void getSpecularComponents:(GLfloat[4] components)
void getDiffuseComponents:(GLfloat[4] components)
BOOL setSunColor:(OOColor *sun_color)
instancetype waypointWithDictionary:(NSDictionary *info)
void setBounty:withReason:(OOCreditsQuantity amount, [withReason] OOLegalStatusReason reason)
void setSystemID:(OOSystemID sid)
void setGuiToStatusScreen()
void setRandom_factor:(int rf)
Vector weaponViewOffset()
OOGalaxyID galaxyNumber()
void setWormhole:(WormholeEntity *newWormhole)
BOOL setUpShipFromDictionary:(NSDictionary *shipDict)
StationEntity * dockedStation()
void setShowDemoShips:(BOOL value)
Quaternion normalOrientation()
BOOL switchHudTo:(NSString *hudFileName)
void addScannedWormhole:(WormholeEntity *wormhole)
void addToAdjustTime:(double seconds)
NSPoint galaxy_coordinates
OOSystemID currentSystemID()
void setGalaxyCoordinates:(NSPoint newPosition)
void runUnsanitizedScriptActions:allowingAIMethods:withContextName:forTarget:(NSArray *unsanitizedActions,[allowingAIMethods] BOOL allowAIMethods,[withContextName] NSString *contextName,[forTarget] ShipEntity *target)
void setJumpCause:(NSString *value)
void setDockedAtMainStation()
void setPreviousSystemID:(OOSystemID sid)
OOMatrix customViewMatrix
Vector customViewUpVector
Vector customViewForwardVector
NSString * dial_clock_adjusted()
BOOL doWorldEventUntilMissionScreen:(jsid message)
PlayerEntity * sharedPlayer()
OOSystemID targetSystemID()
OOSound * ooSoundNamed:inFolder:(NSString *fileName,[inFolder] NSString *folderName)
NSDictionary * dictionaryFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
NSArray * arrayFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
BOOL writeDiagnosticData:toFileNamed:(NSData *data,[toFileNamed] NSString *name)
OOSystemDescriptionManager * systemDescriptionManager()
void setUseAddOns:(NSString *useAddOns)
NSDictionary * roleCategoriesDictionary()
NSDictionary * dictionaryFromFilesNamed:inFolder:mergeMode:cache:(NSString *fileName,[inFolder] NSString *folderName,[mergeMode] OOResourceMergeMode mergeMode,[cache] BOOL useCache)
instancetype elementWithLocation:parent:cost:distance:time:jumps:(OOSystemID location,[parent] OOSystemID parent,[cost] double cost,[distance] double distance,[time] double time,[jumps] int jumps)
void setDemoStartTime:(OOTimeAbsolute time)
void setIsWreckage:(BOOL isw)
void setBounty:withReason:(OOCreditsQuantity amount,[withReason] OOLegalStatusReason reason)
NSDictionary * shipInfoDictionary()
void removeEquipmentItem:(NSString *equipmentKey)
void setFuel:(OOFuelQuantity amount)
void rescaleBy:writeToCache:(GLfloat factor, [writeToCache] BOOL writeToCache)
void setStatus:(OOEntityStatus stat)
void setCargoFlag:(OOCargoFlag flag)
BOOL witchspaceLeavingEffects()
void setRoll:(double amount)
void setDestination:(HPVector dest)
void setGroup:(OOShipGroup *group)
void setSubEntityTakingDamage:(ShipEntity *sub)
void doScriptEvent:(jsid message)
NSArray * portWeaponOffset
void setPrimaryRole:(NSString *role)
NSArray * starboardWeaponOffset
void setHeatInsulation:(GLfloat value)
void setPitch:(double amount)
void enterTargetWormhole()
NSArray * aftWeaponOffset
NSArray * forwardWeaponOffset
void setPendingEscortCount:(uint8_t count)
uint8_t pendingEscortCount()
void setTemperature:(GLfloat value)
void setCrew:(NSArray *crewArray)
void setDemoShip:(OOScalar demoRate)
void doScriptEvent:withArgument:(jsid message,[withArgument] id argument)
void switchAITo:(NSString *aiString)
void setCommodity:andAmount:(OOCommodityType co_type,[andAmount] OOCargoQuantity co_amount)
OOCommodityType commodityType()
BOOL changeProperty:withDictionary:(NSString *key,[withDictionary] NSDictionary *dict)
void setAllowsFastDocking:(BOOL newValue)
void setRequiresDockingClearance:(BOOL newValue)
void setEquivalentTechLevel:(OOTechLevelID value)
unsigned interstellarUndockingAllowed
void setAllegiance:(NSString *newAllegiance)
static OOComparisonResult compareName(id dict1, id dict2, void *context)
static void VerifyDescArray(NSString *key, NSArray *desc)
static void VerifyDescString(NSString *key, NSString *desc)
static BOOL IsCandidateMainStationPredicate(Entity *entity, void *parameter)
NSMutableArray * entities
NSPoint destinationCoordinates()
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
RANROTSeed RanrotSeedFromRandomSeed(Random_Seed seed)
RANROTSeed RANROTGetFullSeed(void)
void ranrot_srand(uint32_t seed)
void OOInitReallyRandom(uint64_t seed)
void RANROTSetFullSeed(RANROTSeed seed)
unsigned RanrotWithSeed(RANROTSeed *ioSeed)
double cunningFee(double value, double precision)
void seed_for_planet_description(Random_Seed s_seed)
RANROTSeed MakeRanrotSeed(uint32_t seed)
void rotate_seed(Random_Seed *seed_ptr)
OOINLINE double distanceBetweenPlanetPositions(int x1, int y1, int x2, int y2) INLINE_CONST_FUNC