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));
470 textureProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-texture.vertex"
471 fragmentShaderName:@"oolite-texture.fragment"
472 prefix:@"#version 330\n"
473 attributeBindings:[NSDictionary dictionary]] retain];
475 blurProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-blur.vertex"
476 fragmentShaderName:@"oolite-blur.fragment"
477 prefix:@"#version 330\n"
478 attributeBindings:[NSDictionary dictionary]] retain];
480 finalProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-final.vertex"
482 fragmentShaderName:[[UNIVERSE gameView] hdrOutput] ? @"oolite-final-hdr.fragment" : @"oolite-final.fragment"
484 fragmentShaderName:@"oolite-final.fragment"
486 prefix:@"#version 330\n"
487 attributeBindings:[NSDictionary dictionary]] retain];
489 OOGL(glGenVertexArrays(1, &quadTextureVAO));
490 OOGL(glGenBuffers(1, &quadTextureVBO));
491 OOGL(glGenBuffers(1, &quadTextureEBO));
493 OOGL(glBindVertexArray(quadTextureVAO));
495 OOGL(glBindBuffer(GL_ARRAY_BUFFER, quadTextureVBO));
498 OOGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadTextureEBO));
501 OOGL(glEnableVertexAttribArray(0));
503 OOGL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float), (
void*)0));
504 OOGL(glEnableVertexAttribArray(1));
506 OOGL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float), (
void*)(2 *
sizeof(
float))));
510 OOGL(glUseProgram(previousProgramID));
511 OOGL(glBindTexture(GL_TEXTURE_2D, previousTextureID));
512 OOGL(glBindVertexArray(previousVAO));
513 OOGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, previousElementBuffer));
514 OOGL(glBindBuffer(GL_ARRAY_BUFFER, previousArrayBuffer));
521 OOGL(glDeleteTextures(1, &msaaTextureID));
522 OOGL(glDeleteTextures(1, &targetTextureID));
523 OOGL(glDeleteTextures(2, passthroughTextureID));
524 OOGL(glDeleteTextures(2, pingpongColorbuffers));
525 OOGL(glDeleteRenderbuffers(1, &msaaDepthBufferID));
526 OOGL(glDeleteRenderbuffers(1, &targetDepthBufferID));
527 OOGL(glDeleteFramebuffers(1, &msaaFramebufferID));
528 OOGL(glDeleteFramebuffers(1, &targetFramebufferID));
529 OOGL(glDeleteFramebuffers(2, pingpongFBO));
530 OOGL(glDeleteFramebuffers(1, &passthroughFramebufferID));
531 OOGL(glDeleteVertexArrays(1, &quadTextureVAO));
532 OOGL(glDeleteBuffers(1, &quadTextureVBO));
533 OOGL(glDeleteBuffers(1, &quadTextureEBO));
534 [textureProgram release];
535 [blurProgram release];
536 [finalProgram release];
540- (void) resizeTargetFramebufferWithViewSize:(NSSize)viewSize
544 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
545 OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, GL_TRUE));
546 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
549 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
550 OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
551 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
554 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
555 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
556 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
558 for (i = 0; i < 2; i++)
560 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]));
561 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
562 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
565 for (i = 0; i < 2; i++)
567 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[i]));
568 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
569 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
573 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, targetDepthBufferID));
574 OOGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
575 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
577 targetFramebufferSize.width = viewSize.width;
578 targetFramebufferSize.height = viewSize.height;
586 OOGL(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previousFBO));
587 GLint previousProgramID;
588 OOGL(glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgramID));
589 GLint previousTextureID;
590 OOGL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureID));
592 OOGL(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previousVAO));
593 GLint previousActiveTexture;
594 OOGL(glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture));
596 OOGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
598 OOGL(glDisable(GL_BLEND));
600 GLhandleARB program = [textureProgram program];
601 GLhandleARB blur = [blurProgram program];
602 GLhandleARB
final = [finalProgram program];
603 NSSize viewSize = [gameView viewSize];
604 float fboResolution[2] = {viewSize.width, viewSize.height};
606 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, passthroughFramebufferID));
607 OOGL(glClear(GL_COLOR_BUFFER_BIT));
609 OOGL(glUseProgram(program));
610 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
611 OOGL(glUniform1i(glGetUniformLocation(program,
"image"), 0));
614 OOGL(glBindVertexArray(quadTextureVAO));
615 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
616 OOGL(glBindVertexArray(0));
618 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
621 BOOL horizontal = YES, firstIteration = YES;
622 unsigned int amount = [
self bloom] ? 10 : 0;
623 OOGL(glUseProgram(blur));
624 for (
unsigned int i = 0; i < amount; i++)
626 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]));
627 OOGL(glUniform1i(glGetUniformLocation(blur,
"horizontal"), horizontal));
628 OOGL(glActiveTexture(GL_TEXTURE0));
630 OOGL(glBindTexture(GL_TEXTURE_2D, firstIteration ? passthroughTextureID[1] : pingpongColorbuffers[!horizontal]));
631 OOGL(glUniform1i(glGetUniformLocation([blurProgram program],
"imageIn"), 0));
632 OOGL(glBindVertexArray(quadTextureVAO));
633 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
634 OOGL(glBindVertexArray(0));
635 horizontal = !horizontal;
638 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
641 OOGL(glUseProgram(
final));
643 OOGL(glActiveTexture(GL_TEXTURE0));
644 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[0]));
645 OOGL(glUniform1i(glGetUniformLocation(
final,
"scene"), 0));
646 OOGL(glUniform1i(glGetUniformLocation(
final,
"bloom"), [
self bloom]));
647 OOGL(glUniform1f(glGetUniformLocation(
final,
"uTime"), [
self getTime]));
648 OOGL(glUniform2fv(glGetUniformLocation(
final,
"uResolution"), 1, fboResolution));
649 OOGL(glUniform1i(glGetUniformLocation(
final,
"uPostFX"), [
self currentPostFX]));
651 if([gameView hdrOutput])
653 OOGL(glUniform1f(glGetUniformLocation(
final,
"uMaxBrightness"), [gameView hdrMaxBrightness]));
654 OOGL(glUniform1f(glGetUniformLocation(
final,
"uPaperWhiteBrightness"), [gameView hdrPaperWhiteBrightness]));
658 OOGL(glActiveTexture(GL_TEXTURE1));
659 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]));
660 OOGL(glUniform1i(glGetUniformLocation(
final,
"bloomBlur"), 1));
661 OOGL(glUniform1f(glGetUniformLocation(
final,
"uSaturation"), [gameView colorSaturation]));
663 OOGL(glBindVertexArray(quadTextureVAO));
664 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
668 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
671 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, previousFBO));
672 OOGL(glActiveTexture(previousActiveTexture));
673 OOGL(glBindTexture(GL_TEXTURE_2D, previousTextureID));
674 OOGL(glUseProgram(previousProgramID));
675 OOGL(glBindVertexArray(previousVAO));
676 OOGL(glEnable(GL_BLEND));
684 [NSException raise:NSInternalInconsistencyException format:@"%s: expected only one Universe to exist at a time.", __PRETTY_FUNCTION__];
690 if (
self ==
nil)
return nil;
696 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
700 useAddOns = [[NSString alloc] initWithString:SCENARIO_OXP_DEFINITION_ALL];
702 [
self setGameView:inGameView];
705 allPlanets = [[NSMutableArray alloc] init];
706 allStations = [[NSMutableSet alloc] init];
713 [
self setDetailLevelDirectly:[prefs oo_intForKey:@"detailLevel"
716 [
self initTargetFramebufferWithViewSize:[gameView viewSize]];
723#if OOLITE_SPEECH_SYNTH
724 OOLog(
@"speech.synthesis",
@"Spoken messages are %@.", ([prefs oo_boolForKey:
@"speech_on" defaultValue:NO] ?
@"on" :
@"off"));
731 [
self loadDescriptions];
735 [
self loadScenarios];
737 autoSave = [prefs oo_boolForKey:@"autosave" defaultValue:NO];
738 wireframeGraphics = [prefs oo_boolForKey:@"wireframe-graphics" defaultValue:NO];
739 doProcedurallyTexturedPlanets = [prefs oo_boolForKey:@"procedurally-textured-planets" defaultValue:YES];
740 [inGameView
setGammaValue:[prefs oo_floatForKey:@"gamma-value" defaultValue:1.0f]];
741 [inGameView
setMsaa:[prefs oo_boolForKey:@"anti-aliasing" defaultValue:NO]];
742 OOLog(
@"MSAA.setup",
@"Multisample anti-aliasing %@requested.", [inGameView msaa] ?
@"" :
@"not ");
743 [inGameView
setFov:OOClamp_0_max_f([prefs oo_floatForKey:@"fov-value" defaultValue:57.2f], MAX_FOV_DEG)
fromFraction:NO];
747#if OOLITE_SPEECH_SYNTH
749 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
759 OOLog(
@"speech.setup.begin",
@"Starting to set up speech synthesizer.");
760 NSSpeechSynthesizer *synth = [[NSSpeechSynthesizer alloc] init];
761 OOLog(
@"speech.setup.end",
@"Finished setting up speech synthesizer.");
762 speechSynthesizer = synth;
766 espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 100, NULL, 0);
767 espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_NONE, 0);
768 espeak_SetParameter(espeakVOLUME, volume, 0);
769 espeak_voices = espeak_ListVoices(NULL);
770 for (espeak_voice_count = 0;
771 espeak_voices[espeak_voice_count];
772 ++espeak_voice_count)
782 entities = [[NSMutableArray arrayWithCapacity:MAX_NUMBER_OF_ENTITIES] retain];
792 waypoints = [[NSMutableDictionary alloc] init];
794 [
self setUpSettings];
805 [
self setUpCargoPods];
809 [
self addEntity:player];
814 [
self setUpInitialUniverse];
817 entitiesDeadThisUpdate = [[NSMutableSet alloc] init];
818 framesDoneThisUpdate = 0;
827 [
self populateNormalSpace];
831#if OO_LOCALIZATION_TOOLS
832 [
self runLocalizationTools];
834 [
self dumpDebugGraphViz];
849 [currentMessage release];
852 [message_gui release];
853 [comm_log_gui release];
857 [commodities release];
859 [_descriptions release];
860 [characters release];
861 [customSounds release];
862 [globalSettings release];
863 [systemManager release];
864 [missiontext release];
865 [equipmentData release];
866 [equipmentDataOutfitting release];
867 [demo_ships release];
869 [screenBackgrounds release];
871 [populatorSettings release];
872 [system_repopulator release];
873 [allPlanets release];
874 [allStations release];
875 [explosionSettings release];
877 [activeWormholes release];
878 [characterPool release];
879 [universeRegion release];
887 for (i = 0; i < 256; i++) [system_names[i] release];
889 [entitiesDeadThisUpdate release];
893#if OOLITE_SPEECH_SYNTH
894 [speechArray release];
896 [speechSynthesizer release];
901 [conditionScripts release];
903 [
self deleteOpenGLObjects];
909- (NSUInteger) sessionID
917 return _doingStartUp;
921- (BOOL) doProcedurallyTexturedPlanets
923 return doProcedurallyTexturedPlanets;
927- (void) setDoProcedurallyTexturedPlanets:(BOOL) value
929 doProcedurallyTexturedPlanets = !!value;
930 [[NSUserDefaults standardUserDefaults] setBool:doProcedurallyTexturedPlanets forKey:@"procedurally-textured-planets"];
934- (NSString *) useAddOns
940- (BOOL) setUseAddOns:(NSString *) newUse fromSaveGame:(BOOL) saveGame
942 return [
self setUseAddOns:newUse fromSaveGame:saveGame forceReinit:NO];
946- (BOOL) setUseAddOns:(NSString *) newUse fromSaveGame:(BOOL) saveGame forceReinit:(BOOL)force
948 if (!force && [newUse isEqualToString:useAddOns])
953 useAddOns = [newUse retain];
955 return [
self reinitAndShowDemo:!saveGame];
960- (NSUInteger) entityCount
962 return [entities count];
967- (void) debugDumpEntities
970 int show_count = n_entities;
974 OOLog(
@"universe.objectDump",
@"DEBUG: Entity Dump - [entities count] = %lu,\tn_entities = %u", [entities
count], n_entities);
977 for (i = 0; i < show_count; i++)
979 OOLog(
@"universe.objectDump",
@"Ent:%4u %@", i, [sortedEntities[i] descriptionForObjDump]);
983 if ([entities
count] != n_entities)
985 OOLog(
@"universe.objectDump",
@"entities = %@", [entities description]);
990- (NSArray *) entityList
992 return [NSArray arrayWithArray:entities];
1002 [
self setPauseMessageVisible:NO];
1003 NSString *pauseKey = [PLAYER keyBindingDescription2:@"key_pausebutton"];
1005 if ([player status] == STATUS_DOCKED)
1007 if ([gui setForegroundTextureKey:
@"paused_docked_overlay"])
1009 [gui drawGUI:1.0 drawCursor:NO];
1013 [
self setPauseMessageVisible:YES];
1014 [
self addMessage:OOExpandKey(@"game-paused-docked", pauseKey) forCount:1.0];
1019 if ([player guiScreen] != GUI_SCREEN_MAIN && [gui setForegroundTextureKey:
@"paused_overlay"])
1021 [gui drawGUI:1.0 drawCursor:NO];
1025 [
self setPauseMessageVisible:YES];
1026 [
self addMessage:OOExpandKey(@"game-paused", pauseKey) forCount:1.0];
1030 [[
self gameController] setGamePaused:YES];
1044 ShipScriptEvent(context, player,
"shipWillEnterWitchspace", STRING_TO_JSVAL(JS_InternString(context, [[player jumpCause] UTF8String])), INT_TO_JSVAL(dest));
1047 [
self allShipsDoScriptEvent:OOJSID("playerWillEnterWitchspace") andReactToAIMessage:@"PLAYER WITCHSPACE"];
1054 [
self removeAllEntitiesExceptPlayer];
1059 if (![wormhole withMisjump])
1062 [
self setSystemTo: dest];
1065 [
self populateNormalSpace];
1073 [
self setUpWitchspaceBetweenSystem:[wormhole
origin] andSystem:[wormhole
destination]];
1082 [UNIVERSE setSkyColorRed:0.0f
1087 [
self setWitchspaceBreakPattern:YES];
1095- (void) setUpUniverseFromStation
1105 OOSystemID sys = [
self findSystemNumberAtCoords:coords withGalaxy:[player
galaxyNumber] includingHidden:YES];
1110 if (dockedStation && !interstel)
1114 [
self setSystemTo: sys];
1116 while ([entities
count] > 2)
1118 Entity *ent = [entities objectAtIndex:index];
1119 if ((ent != player)&&(ent != dockedStation))
1123 [
self removeEntity:ent];
1133 if (dockedStation ==
nil) [
self removeAllEntitiesExceptPlayer];
1136 if (!dockedStation || !interstel)
1139 [
self populateNormalSpace];
1142 if ([dockedStation maxFlightSpeed] > 0)
1144 float d1 = [
self randomDistanceWithinScanner];
1145 HPVector pos = [UNIVERSE getWitchspaceExitPosition];
1149 if (abs((
int)d1) < 2750)
1151 d1 += ((d1 > 0.0)? 2750.0f: -2750.0f);
1160 [
self setWitchspaceBreakPattern:YES];
1168 if(!autoSaveNow) [
self setViewDirection:VIEW_FORWARD];
1172 [UNIVERSE setSkyColorRed:0.0f
1179- (void) setUpUniverseFromWitchspace
1186 if ([entities
count] == 0)
1191 [
self addEntity:player];
1197 player = [PLAYER retain];
1201 [
self populateNormalSpace];
1206 [
self setViewDirection:VIEW_FORWARD];
1208 [comm_log_gui printLongText:[NSString stringWithFormat:@"%@ %@", [
self getSystemName:systemID], [player
dial_clock_adjusted]]
1215- (void) setUpUniverseFromMisjump
1222 if ([entities
count] == 0)
1227 [
self addEntity:player];
1233 player = [PLAYER retain];
1236 [
self setUpWitchspace];
1239 [
self setAirResistanceFactor:0.0f];
1244 [
self setViewDirection:VIEW_FORWARD];
1250- (void) setUpWitchspace
1252 [
self setUpWitchspaceBetweenSystem:[PLAYER systemID] andSystem:[PLAYER nextHopTargetSystemID]];
1264 NSString* override_key = [
self keyForInterstellarOverridesForSystems:s1 :s2 inGalaxy:galaxyID];
1266 NSDictionary *systeminfo = [systemManager getPropertiesForSystemKey:override_key];
1268 [universeRegion clearSubregions];
1275 thing = [[
SkyEntity alloc] initWithColors:col1:col2 andSystemInfo: systeminfo];
1279 [
self addEntity:thing];
1285 [
self addEntity:thing];
1288 ambientLightLevel = [systeminfo oo_floatForKey:@"ambient_level" defaultValue:1.0];
1294 [
self clearSystemPopulator];
1295 NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:@"interstellarSpaceWillPopulate"];
1296 [system_repopulator release];
1297 system_repopulator = [[systeminfo oo_stringForKey:@"repopulator" defaultValue:@"interstellarSpaceWillRepopulate"] retain];
1299 [PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
1301 [
self populateSystemFromDictionariesWithSun:nil andPlanet:nil];
1304 NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
1305 if (script_actions !=
nil)
1307 OOStandardsDeprecated([NSString stringWithFormat:
@"The script_actions system info key is deprecated for %@.",override_key]);
1323- (OOPlanetEntity *) setUpPlanet
1326 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1329 NSMutableDictionary *planetDict = [NSMutableDictionary dictionaryWithDictionary:[systemManager getPropertiesForCurrentSystem]];
1330 [planetDict oo_setBool:YES forKey:@"mainForLocalSystem"];
1331 OOPlanetEntity *a_planet = [[OOPlanetEntity alloc] initFromDictionary:planetDict withAtmosphere:[planetDict oo_boolForKey:@"has_atmosphere" defaultValue:YES] andSeed:systemSeed forSystem:systemID];
1333 double planet_zpos = [planetDict oo_floatForKey:@"planet_distance" defaultValue:500000];
1334 planet_zpos *= [planetDict oo_floatForKey:@"planet_distance_multiplier" defaultValue:1.0];
1336#ifdef OO_DUMP_PLANETINFO
1337 OOLog(
@"planetinfo.record",
@"planet zpos = %f",planet_zpos);
1339 [a_planet setPosition:(HPVector){ 0, 0, planet_zpos }];
1340 [a_planet setEnergy:1000000.0];
1342 if ([allPlanets
count]>0)
1344 OOPlanetEntity *tmp=[allPlanets objectAtIndex:0];
1345 [
self addEntity:a_planet];
1346 [allPlanets removeObject:a_planet];
1347 cachedPlanet=a_planet;
1348 [allPlanets replaceObjectAtIndex:0 withObject:a_planet];
1349 [
self removeEntity:(Entity *)tmp];
1353 [
self addEntity:a_planet];
1355 return [a_planet autorelease];
1367 OOPlanetEntity *a_planet;
1369 HPVector stationPos;
1374 NSDictionary *systeminfo = [systemManager getPropertiesForCurrentSystem];
1375 unsigned techlevel = [systeminfo oo_unsignedIntForKey:KEY_TECHLEVEL];
1376 NSString *stationDesc =
nil, *defaultStationDesc =
nil;
1381 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1385 sunGoneNova = [systeminfo oo_boolForKey:@"sun_gone_nova" defaultValue:NO];
1388 [universeRegion clearSubregions];
1391 [
self setSkyColorRed:0.0f
1397#ifdef OO_DUMP_PLANETINFO
1398 OOLog(
@"planetinfo.record",
@"seed = %d %d %d %d",system_seed.c,system_seed.d,system_seed.e,system_seed.f);
1399 OOLog(
@"planetinfo.record",
@"coordinates = %d %d",system_seed.d,system_seed.b);
1401#define SPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = \"%@\";",[systeminfo oo_stringForKey:@"" #PROP]);
1402#define IPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %d;",[systeminfo oo_intForKey:@#PROP]);
1403#define FPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %f;",[systeminfo oo_floatForKey:@"" #PROP]);
1408 IPROP(productivity);
1421 float h2 = h1 + 1.0 / (1.0 + (
Ranrot() % 5));
1427 thing = [[
SkyEntity alloc] initWithColors:col1:col2 andSystemInfo: systeminfo];
1429 [
self addEntity:thing];
1438 ambientLightLevel = [systeminfo oo_floatForKey:@"ambient_level" defaultValue:1.0];
1442 dict_object=[systeminfo objectForKey:@"sun_color"];
1443 if (dict_object!=
nil)
1459 [
self addEntity:thing];
1464 float defaultSunFlare =
randf()*0.1;
1465 float defaultSunHues = 0.5+
randf()*0.5;
1471 a_planet=[
self setUpPlanet];
1472 double planet_radius = [a_planet radius];
1481 double sun_distance;
1482 double sunDistanceModifier;
1483 double safeDistance;
1486 sunDistanceModifier = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_modifier" defaultValue:0.0];
1487 if (sunDistanceModifier < 6.0)
1489 sun_distance = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance" defaultValue:(planet_radius*20)];
1491 sun_distance *= [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_multiplier" defaultValue:1];
1495 sun_distance = planet_radius * sunDistanceModifier;
1498 sun_radius = [systeminfo oo_nonNegativeDoubleForKey:@"sun_radius" defaultValue:2.5 * planet_radius];
1500 if ((sun_radius < 1000.0) || (sun_radius > sun_distance / 2 && !sunGoneNova))
1502 OOLogWARN(
@"universe.setup.badSun",
@"Sun radius of %f is not valid for this system",sun_radius);
1503 sun_radius = sun_radius < 1000.0 ? 1000.0 : (sun_distance / 2);
1505#ifdef OO_DUMP_PLANETINFO
1506 OOLog(
@"planetinfo.record",
@"sun_radius = %f",sun_radius);
1508 safeDistance=36 * sun_radius * sun_radius;
1512 HPVector sun_dir = [systeminfo oo_hpvectorForKey:@"sun_vector"];
1513 sun_distance /= 2.0;
1516 sun_distance *= 2.0;
1517 sunPos = HPvector_subtract([a_planet position],
1518 HPvector_multiply_scalar(sun_dir,sun_distance));
1522 while (HPmagnitude2(sunPos) < safeDistance);
1526 [a_planet setOrientation:quaternion_rotation_betweenHP(sun_dir,make_HPvector(1.0,0.0,0.0))];
1528#ifdef OO_DUMP_PLANETINFO
1529 OOLog(
@"planetinfo.record",
@"sun_vector = %.3f %.3f %.3f",vf.x,vf.y,vf.z);
1530 OOLog(
@"planetinfo.record",
@"sun_distance = %.0f",sun_distance);
1535 NSMutableDictionary *sun_dict = [NSMutableDictionary dictionaryWithCapacity:5];
1536 [sun_dict setObject:[NSNumber numberWithDouble:sun_radius] forKey:@"sun_radius"];
1537 dict_object=[systeminfo objectForKey: @"corona_shimmer"];
1538 if (dict_object!=
nil) [sun_dict setObject:dict_object forKey:@"corona_shimmer"];
1539 dict_object=[systeminfo objectForKey: @"corona_hues"];
1540 if (dict_object!=
nil)
1542 [sun_dict setObject:dict_object forKey:@"corona_hues"];
1546 [sun_dict setObject:[NSNumber numberWithFloat:defaultSunHues] forKey:@"corona_hues"];
1548 dict_object=[systeminfo objectForKey: @"corona_flare"];
1549 if (dict_object!=
nil)
1551 [sun_dict setObject:dict_object forKey:@"corona_flare"];
1555 [sun_dict setObject:[NSNumber numberWithFloat:defaultSunFlare] forKey:@"corona_flare"];
1557 dict_object=[systeminfo objectForKey:KEY_SUNNAME];
1558 if (dict_object!=
nil)
1560 [sun_dict setObject:dict_object forKey:KEY_SUNNAME];
1562#ifdef OO_DUMP_PLANETINFO
1563 OOLog(
@"planetinfo.record",
@"corona_flare = %f",[sun_dict oo_floatForKey:
@"corona_flare"]);
1564 OOLog(
@"planetinfo.record",
@"corona_hues = %f",[sun_dict oo_floatForKey:
@"corona_hues"]);
1565 OOLog(
@"planetinfo.record",
@"sun_color = %@",[bgcolor descriptionComponents]);
1567 a_sun = [[
OOSunEntity alloc] initSunWithColor:bgcolor andDictionary:sun_dict];
1572 [
self addEntity:a_sun];
1587 stationPos = [a_planet position];
1589 vf = [systeminfo oo_vectorForKey:@"station_vector"];
1590#ifdef OO_DUMP_PLANETINFO
1591 OOLog(
@"planetinfo.record",
@"station_vector = %.3f %.3f %.3f",vf.x,vf.y,vf.z);
1593 stationPos = HPvector_subtract(stationPos, vectorToHPVector(vector_multiply_scalar(vf, 2.0 * planet_radius)));
1597 stationDesc = [systeminfo oo_stringForKey:@"station" defaultValue:@"coriolis"];
1598#ifdef OO_DUMP_PLANETINFO
1599 OOLog(
@"planetinfo.record",
@"station = %@",stationDesc);
1602 a_station = (
StationEntity *)[
self newShipWithRole:stationDesc];
1614 if (![a_station isStation] || ![a_station validForAddToUniverse])
1616 if (a_station ==
nil)
1619 OOLog(
@"universe.setup.badStation",
@"Failed to set up a ship for role \"%@\
" as system station, trying again with \"%@\".", stationDesc, defaultStationDesc);
1623 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);
1625 [a_station release];
1626 stationDesc = defaultStationDesc;
1627 a_station = (
StationEntity *)[
self newShipWithRole:stationDesc];
1629 if (![a_station isStation] || ![a_station validForAddToUniverse])
1631 if (a_station ==
nil)
1633 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);
1637 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);
1639 [a_station release];
1641 a_station = (
StationEntity *)[
self newShipWithName:
@"coriolis-station"];
1642 if (![a_station isStation] || ![a_station validForAddToUniverse])
1644 OOLog(
@"universe.setup.badStation",
@"%@",
@"Could not create built-in Coriolis station! Generating a stationless system.");
1650 if (a_station !=
nil)
1652 [a_station
setOrientation:quaternion_rotation_between(vf,make_vector(0.0,0.0,1.0))];
1658 [
self addEntity:a_station];
1666 cachedPlanet = a_planet;
1667 cachedStation = a_station;
1673 [
self populateSpaceFromActiveWormholes];
1677 [a_station release];
1681- (void) populateNormalSpace
1683 NSDictionary *systeminfo = [systemManager getPropertiesForCurrentSystem];
1685 BOOL sunGoneNova = [systeminfo oo_boolForKey:@"sun_gone_nova"];
1691 HPVector v0 = make_HPvector(0,0,34567.89);
1692 double min_safe_dist2 = 6000000.0 * 6000000.0;
1693 HPVector sunPos = [cachedSun position];
1694 while (HPmagnitude2(cachedSun->position) < min_safe_dist2)
1698 sunPos = HPvector_add(sunPos, v0);
1699 [cachedSun setPosition:sunPos];
1703 [
self removeEntity:cachedPlanet];
1705 [
self removeEntity:cachedStation];
1706 cachedStation =
nil;
1711 [
self clearSystemPopulator];
1713 if ([
PLAYER status] != STATUS_START_GAME)
1715 NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:(sunGoneNova)?@"novaSystemWillPopulate":@"systemWillPopulate"];
1716 [system_repopulator release];
1717 system_repopulator = [[systeminfo oo_stringForKey:@"repopulator" defaultValue:(sunGoneNova)?@"novaSystemWillRepopulate":@"systemWillRepopulate"] retain];
1720 [PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
1722 [
self populateSystemFromDictionariesWithSun:cachedSun andPlanet:cachedPlanet];
1728 NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
1729 if (script_actions !=
nil)
1731 OOStandardsDeprecated([NSString stringWithFormat:
@"The script_actions system info key is deprecated for %@.",[
self getSystemName:systemID]]);
1735 [PLAYER runUnsanitizedScriptActions:script_actions
1736 allowingAIMethods:NO
1737 withContextName:@"<system script_actions>"
1747- (void) clearSystemPopulator
1749 [populatorSettings release];
1750 populatorSettings = [[NSMutableDictionary alloc] initWithCapacity:128];
1754- (NSDictionary *) getPopulatorSettings
1756 return populatorSettings;
1760- (void) setPopulatorSetting:(NSString *)key to:(NSDictionary *)setting
1764 [populatorSettings removeObjectForKey:key];
1768 [populatorSettings setObject:setting forKey:key];
1773- (BOOL) deterministicPopulation
1775 return deterministic_population;
1779- (void) populateSystemFromDictionariesWithSun:(
OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet
1781 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1782 NSArray *blocks = [populatorSettings allValues];
1783 NSEnumerator *enumerator = [[blocks sortedArrayUsingFunction:populatorPrioritySort context:nil] objectEnumerator];
1784 NSDictionary *populator =
nil;
1786 uint32_t i, locationSeed, groupCount, rndvalue;
1789 NSString *locationCode =
nil;
1791 while ((populator = [enumerator nextObject]))
1793 deterministic_population = [populator oo_boolForKey:@"deterministic" defaultValue:NO];
1797 deterministic_population = NO;
1800 locationSeed = [populator oo_unsignedIntForKey:@"locationSeed" defaultValue:0];
1801 groupCount = [populator oo_unsignedIntForKey:@"groupCount" defaultValue:1];
1803 for (i = 0; i < groupCount; i++)
1805 locationCode = [populator oo_stringForKey:@"location" defaultValue:@"COORDINATES"];
1806 if ([locationCode isEqualToString:
@"COORDINATES"])
1808 location = [populator oo_hpvectorForKey:@"coordinates" defaultValue:kZeroHPVector];
1812 if (locationSeed != 0)
1828 deterministic_population = NO;
1830 if (sun ==
nil || planet ==
nil)
1833 location = [
self locationByCode:@"WITCHPOINT" withSun:nil andPlanet:nil];
1837 location = [
self locationByCode:locationCode withSun:sun andPlanet:planet];
1839 if(locationSeed != 0)
1846 pdef = [populator objectForKey:@"callbackObj"];
1851 deterministic_population = NO;
1869- (HPVector) locationByCode:(NSString *)code withSun:(
OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet
1872 if ([code isEqualToString:
@"WITCHPOINT"] || sun ==
nil || planet ==
nil || [sun goneNova])
1879 if ([code isEqualToString:
@"LANE_WPS"])
1882 double l1 = HPmagnitude([planet position]);
1883 double l2 = HPmagnitude(HPvector_subtract([sun position],[planet position]));
1884 double l3 = HPmagnitude([sun position]);
1885 double total = l1+l2+l3;
1886 float choice =
randf();
1887 if (choice < l1/total)
1889 return [
self locationByCode:@"LANE_WP" withSun:sun andPlanet:planet];
1891 else if (choice < (l1+l2)/total)
1893 return [
self locationByCode:@"LANE_PS" withSun:sun andPlanet:planet];
1897 return [
self locationByCode:@"LANE_WS" withSun:sun andPlanet:planet];
1900 else if ([code isEqualToString:
@"LANE_WP"])
1904 else if ([code isEqualToString:
@"LANE_WS"])
1908 else if ([code isEqualToString:
@"LANE_PS"])
1912 else if ([code isEqualToString:
@"STATION_AEGIS"])
1917 }
while(HPdistance2(result,[planet position])<[planet radius]*[planet radius]*1.5);
1920 else if ([code isEqualToString:
@"PLANET_ORBIT_LOW"])
1924 else if ([code isEqualToString:
@"PLANET_ORBIT"])
1928 else if ([code isEqualToString:
@"PLANET_ORBIT_HIGH"])
1932 else if ([code isEqualToString:
@"STAR_ORBIT_LOW"])
1936 else if ([code isEqualToString:
@"STAR_ORBIT"])
1940 else if ([code isEqualToString:
@"STAR_ORBIT_HIGH"])
1944 else if ([code isEqualToString:
@"TRIANGLE"])
1957 result = HPvector_add(HPvector_multiply_scalar([planet position],r),HPvector_multiply_scalar([sun position],s));
1960 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);
1962 else if ([code isEqualToString:
@"INNER_SYSTEM"])
1965 result =
OORandomPositionInShell([sun position],[sun radius]*3.0,HPdistance([sun position],[planet position]));
1969 }
while (HPdistance2(result,[sun position]) < [sun radius]*[sun radius]*9.0);
1971 else if ([code isEqualToString:
@"INNER_SYSTEM_OFFPLANE"])
1973 result =
OORandomPositionInShell([sun position],[sun radius]*3.0,HPdistance([sun position],[planet position]));
1975 else if ([code isEqualToString:
@"OUTER_SYSTEM"])
1977 result =
OORandomPositionInShell([sun position],HPdistance([sun position],[planet position]),HPdistance([sun position],[planet position])*10.0);
1981 else if ([code isEqualToString:
@"OUTER_SYSTEM_OFFPLANE"])
1983 result =
OORandomPositionInShell([sun position],HPdistance([sun position],[planet position]),HPdistance([sun position],[planet position])*10.0);
1995- (void) setAmbientLightLevel:(
float)newValue
1997 NSAssert(
UNIVERSE !=
nil,
@"Attempt to set ambient light level with a non yet existent universe.");
1999 ambientLightLevel = OOClamp_0_max_f(newValue, 10.0f);
2004- (float) ambientLightLevel
2006 return ambientLightLevel;
2030 GLfloat sun_pos[] = {0.0, 0.0, 0.0, 1.0};
2031 GLfloat sun_ambient[] = {0.0, 0.0, 0.0, 1.0};
2034 for (i = n_entities - 1; i > 0; i--)
2035 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[SkyEntity class]]))
2036 the_sky = (
SkyEntity*)sortedEntities[i];
2042 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
2043 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
2044 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
2052 stars_ambient[0] = 0.05; stars_ambient[1] = 0.20; stars_ambient[2] = 0.05; stars_ambient[3] = 1.0;
2053 sun_diffuse[0] = 0.85; sun_diffuse[1] = 1.0; sun_diffuse[2] = 0.85; sun_diffuse[3] = 1.0;
2054 sun_specular[0] = 0.95; sun_specular[1] = 1.0; sun_specular[2] = 0.95; sun_specular[3] = 1.0;
2055 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
2056 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
2057 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
2060 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, sun_pos));
2066 [[the_sky skyColor] getRed:&r green:&g blue:&b alpha:&a];
2070 GLfloat ambient_level = [
self ambientLightLevel];
2074 stars_ambient[3] = 1.0;
2082 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
2087- (void) forceLightSwitch
2093- (void) setMainLightPosition: (Vector) sunPos
2095 main_light_position[0] = sunPos.x;
2096 main_light_position[1] = sunPos.y;
2097 main_light_position[2] = sunPos.z;
2098 main_light_position[3] = 1.0;
2102- (
ShipEntity *) addShipWithRole:(NSString *)desc launchPos:(HPVector)launchPos rfactor:(GLfloat)rfactor
2107 launchPos.x += 2 * rfactor * (
randf() - 0.5);
2108 launchPos.y += 2 * rfactor * (
randf() - 0.5);
2109 launchPos.z += 2 * rfactor * (
randf() - 0.5);
2112 ShipEntity *ship = [
self newShipWithRole:desc];
2119 if ([ship hasRole:
@"cargopod"]) [
self fillCargopodWithRandomCargo:ship];
2122 if (![ship crew] && ![ship isUnpiloted])
2123 [ship
setCrew:[NSArray arrayWithObject:
2127 if ([ship scanClass] == CLASS_NOT_SET)
2131 [
self addEntity:ship];
2139- (void) addShipWithRole:(NSString *) desc nearRouteOneAt:(
double) route_fraction
2143 Entity *theStation = [
self station];
2149 HPVector launchPos = OOHPVectorInterpolate([
self getWitchspaceExitPosition], [theStation position], route_fraction);
2151 [
self addShipWithRole:desc launchPos:launchPos rfactor:SCANNER_MAX_RANGE];
2155- (HPVector) coordinatesForPosition:(HPVector) pos withCoordinateSystem:(NSString *) system returningScalar:(GLfloat*) my_scalar
2192 NSString* l_sys = [system lowercaseString];
2193 if ([l_sys length] != 3)
2195 OOPlanetEntity* the_planet = [
self planet];
2197 if (the_planet ==
nil || the_sun ==
nil || [l_sys isEqualToString:
@"abs"])
2199 if (my_scalar) *my_scalar = 1.0;
2202 HPVector w_pos = [
self getWitchspaceExitPosition];
2203 HPVector p_pos = the_planet->position;
2204 HPVector s_pos = the_sun->
position;
2206 const char* c_sys = [l_sys UTF8String];
2207 HPVector p0, p1, p2;
2216 p1 = p_pos; p2 = s_pos;
break;
2218 p1 = s_pos; p2 = p_pos;
break;
2228 p1 = w_pos; p2 = s_pos;
break;
2230 p1 = s_pos; p2 = w_pos;
break;
2240 p1 = w_pos; p2 = p_pos;
break;
2242 p1 = p_pos; p2 = w_pos;
break;
2250 HPVector k = HPvector_normal_or_zbasis(HPvector_subtract(p1, p0));
2251 HPVector v = HPvector_normal_or_xbasis(HPvector_subtract(p2, p0));
2253 HPVector j = HPcross_product(k, v);
2254 HPVector i = HPcross_product(j, k);
2256 GLfloat scale = 1.0;
2260 scale = [the_planet radius];
2264 scale = [the_sun
radius];
2268 scale = HPmagnitude(HPvector_subtract(p1, p0));
2282 HPVector result = p0;
2283 result.x += scale * (pos.
x * i.
x + pos.
y * j.
x + pos.z * k.
x);
2284 result.y += scale * (pos.
x * i.
y + pos.
y * j.
y + pos.z * k.
y);
2285 result.z += scale * (pos.
x * i.z + pos.
y * j.z + pos.z * k.z);
2291- (NSString *) expressPosition:(HPVector) pos inCoordinateSystem:(NSString *) system
2293 HPVector result = [
self legacyPositionFrom:pos asCoordinateSystem:system];
2294 return [NSString stringWithFormat:@"%@ %.2f %.2f %.2f", system, result.x, result.y, result.z];
2298- (HPVector) legacyPositionFrom:(HPVector) pos asCoordinateSystem:(NSString *) system
2300 NSString* l_sys = [system lowercaseString];
2301 if ([l_sys length] != 3)
2303 OOPlanetEntity* the_planet = [
self planet];
2305 if (the_planet ==
nil || the_sun ==
nil || [l_sys isEqualToString:
@"abs"])
2309 HPVector w_pos = [
self getWitchspaceExitPosition];
2310 HPVector p_pos = the_planet->
position;
2311 HPVector s_pos = the_sun->
position;
2313 const char* c_sys = [l_sys UTF8String];
2314 HPVector p0, p1, p2;
2323 p1 = p_pos; p2 = s_pos;
break;
2325 p1 = s_pos; p2 = p_pos;
break;
2335 p1 = w_pos; p2 = s_pos;
break;
2337 p1 = s_pos; p2 = w_pos;
break;
2347 p1 = w_pos; p2 = p_pos;
break;
2349 p1 = p_pos; p2 = w_pos;
break;
2357 HPVector k = HPvector_normal_or_zbasis(HPvector_subtract(p1, p0));
2358 HPVector v = HPvector_normal_or_xbasis(HPvector_subtract(p2, p0));
2360 HPVector j = HPcross_product(k, v);
2361 HPVector i = HPcross_product(j, k);
2363 GLfloat scale = 1.0;
2368 scale = 1.0f / [the_planet radius];
2373 scale = 1.0f / [the_sun
radius];
2378 scale = 1.0f / HPdistance(p1, p0);
2390 HPVector r_pos = HPvector_subtract(pos, p0);
2391 HPVector result = make_HPvector(scale * (r_pos.x * i.x + r_pos.y * i.y + r_pos.z * i.z),
2392 scale * (r_pos.x * j.x + r_pos.y * j.y + r_pos.z * j.z),
2393 scale * (r_pos.x * k.x + r_pos.y * k.y + r_pos.z * k.z) );
2399- (HPVector) coordinatesFromCoordinateSystemString:(NSString *) system_x_y_z
2402 if ([tokens
count] != 4)
2405 return make_HPvector(0,0,0);
2408 return [
self coordinatesForPosition:make_HPvector([tokens oo_floatAtIndex:1], [tokens oo_floatAtIndex:2], [tokens oo_floatAtIndex:3]) withCoordinateSystem:[tokens oo_stringAtIndex:0] returningScalar:&dummy];
2412- (BOOL) addShipWithRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2415 GLfloat scalar = 1.0;
2416 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2418 GLfloat rfactor = scalar;
2424 return ([
self addShipWithRole:desc launchPos:launchPos rfactor:rfactor] !=
nil);
2428- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc atPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2431 GLfloat scalar = 1.0;
2432 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2433 GLfloat distance_from_center = 0.0;
2434 HPVector v_from_center, ship_pos;
2435 HPVector ship_positions[howMany];
2437 int scale_up_after = 0;
2438 int current_shell = 0;
2439 GLfloat walk_factor = 2.0;
2442 ShipEntity *ship = [
self addShipWithRole:desc launchPos:launchPos rfactor:0.0];
2443 if (ship ==
nil)
return NO;
2449 int limit_count = 8;
2456 v_from_center.x += walk_factor * (
randf() - 0.5);
2457 v_from_center.y += walk_factor * (
randf() - 0.5);
2458 v_from_center.z += walk_factor * (
randf() - 0.5);
2459 }
while ((v_from_center.x == 0.0)&&(v_from_center.y == 0.0)&&(v_from_center.z == 0.0));
2460 v_from_center = HPvector_normal(v_from_center);
2462 ship_pos = make_HPvector( launchPos.x + distance_from_center * v_from_center.x,
2463 launchPos.y + distance_from_center * v_from_center.y,
2464 launchPos.z + distance_from_center * v_from_center.z);
2469 while (safe && (j >= current_shell))
2471 safe = (safe && (HPdistance2(ship_pos, ship_positions[j]) > safe_distance2));
2480 distance_from_center += sqrt(safe_distance2);
2487 [ship setScanClass:scanClass == CLASS_NOT_SET ? CLASS_NEUTRAL : scanClass];
2495 ship_positions[i] = ship_pos;
2497 if (i > scale_up_after)
2500 scale_up_after += 1 + 2 * i;
2501 distance_from_center += sqrt(safe_distance2);
2508- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2511 GLfloat scalar = 1.0;
2512 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2513 GLfloat rfactor = scalar;
2518 BoundingBox launch_bbox;
2519 bounding_box_reset_to_vector(&launch_bbox, make_vector(launchPos.x - rfactor, launchPos.y - rfactor, launchPos.z - rfactor));
2520 bounding_box_add_xyz(&launch_bbox, launchPos.x + rfactor, launchPos.y + rfactor, launchPos.z + rfactor);
2522 return [
self addShips: howMany withRole: desc intoBoundingBox: launch_bbox];
2526- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system withinRadius:(GLfloat) radius
2529 GLfloat scalar = 1.0;
2530 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2531 GLfloat rfactor = radius;
2534 BoundingBox launch_bbox;
2535 bounding_box_reset_to_vector(&launch_bbox, make_vector(launchPos.x - rfactor, launchPos.y - rfactor, launchPos.z - rfactor));
2536 bounding_box_add_xyz(&launch_bbox, launchPos.x + rfactor, launchPos.y + rfactor, launchPos.z + rfactor);
2538 return [
self addShips: howMany withRole: desc intoBoundingBox: launch_bbox];
2542- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc intoBoundingBox:(BoundingBox) bbox
2549 int h0 = howMany / 2;
2550 int h1 = howMany - h0;
2552 GLfloat lx = bbox.max.x - bbox.min.
x;
2553 GLfloat ly = bbox.max.y - bbox.min.
y;
2554 GLfloat lz = bbox.max.z - bbox.min.z;
2555 BoundingBox bbox0 = bbox;
2556 BoundingBox bbox1 = bbox;
2557 if ((lx > lz)&&(lx > ly))
2559 bbox0.min.x += 0.5 * lx;
2560 bbox1.max.x -= 0.5 * lx;
2566 bbox0.min.y += 0.5 * ly;
2567 bbox1.max.y -= 0.5 * ly;
2571 bbox0.min.z += 0.5 * lz;
2572 bbox1.max.z -= 0.5 * lz;
2576 return ([
self addShips: h0 withRole: desc intoBoundingBox: bbox0] && [
self addShips: h1 withRole: desc intoBoundingBox: bbox1]);
2580 HPVector pos = make_HPvector(bbox.min.x, bbox.min.y, bbox.min.z);
2581 pos.x += 0.5 * (
randf() +
randf()) * (bbox.max.
x - bbox.min.
x);
2582 pos.y += 0.5 * (
randf() +
randf()) * (bbox.max.
y - bbox.min.
y);
2583 pos.z += 0.5 * (
randf() +
randf()) * (bbox.max.z - bbox.min.z);
2585 return ([
self addShipWithRole:desc launchPos:pos rfactor:0.0] !=
nil);
2589- (BOOL) spawnShip:(NSString *) shipdesc
2593 OOStandardsDeprecated([NSString stringWithFormat:
@"'spawn' via legacy script is deprecated as a way of adding ships for %@",shipdesc]);
2596 NSDictionary *shipdict =
nil;
2599 if (shipdict ==
nil)
return NO;
2601 ship = [
self newShipWithName:shipdesc];
2603 if (ship ==
nil)
return NO;
2606 NSDictionary *spawndict = [shipdict oo_dictionaryForKey:@"spawn"];
2607 HPVector pos, rpos, spos;
2608 NSString *positionString =
nil;
2611 positionString = [spawndict oo_stringForKey:@"position"];
2612 if (positionString !=
nil)
2614 if([positionString hasPrefix:
@"abs "] && ([
self planet] !=
nil || [
self sun] !=
nil))
2616 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);
2619 pos = [
self coordinatesFromCoordinateSystemString:positionString];
2625 OOLogERR(
@"universe.spawnShip.error",
@"***** ERROR: failed to find a spawn position for ship %@.", shipdesc);
2630 positionString = [spawndict oo_stringForKey:@"facing_position"];
2631 if (positionString !=
nil)
2633 if([positionString hasPrefix:
@"abs "] && ([
self planet] !=
nil || [
self sun] !=
nil))
2635 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);
2640 rpos = [
self coordinatesFromCoordinateSystemString:positionString];
2641 rpos = HPvector_subtract(rpos, spos);
2645 rpos = HPvector_normal(rpos);
2654 q1 = make_quaternion(0,1,0,0);
2662 [
self addEntity:ship];
2669- (void) witchspaceShipWithPrimaryRole:(NSString *)role
2673 NSDictionary *systeminfo =
nil;
2676 systeminfo = [
self currentSystemData];
2677 government = [systeminfo oo_unsignedCharForKey:KEY_GOVERNMENT];
2679 ship = [
self newShipWithRole:role];
2682 if (ship && [ship hasRole:
@"cargopod"])
2684 [
self fillCargopodWithRandomCargo:ship];
2689 if (([ship scanClass] == CLASS_NO_DRAW)||([ship scanClass] == CLASS_NOT_SET))
2691 if ([role isEqual:
@"trader"])
2694 if ([ship hasRole:
@"sunskim-trader"] &&
randf() < 0.25)
2697 [
self makeSunSkimmer:ship andSetAI:YES];
2704 if (([ship pendingEscortCount] > 0)&&((
Ranrot() % 7) < government))
2707 [ship setPendingEscortCount:(nx > 0) ? nx : 0];
2710 if ([role isEqual:
@"pirate"])
2713 [ship
setBounty: (Ranrot() & 7) + (Ranrot() & 7) + ((randf() < 0.05)? 63 : 23)
withReason:kOOLegalStatusReasonSetup];
2715 if ([ship crew] ==
nil && ![ship isUnpiloted])
2716 [ship
setCrew:[NSArray arrayWithObject:
2729 if (entity ==
nil)
return nil;
2739 ship = [
self addShipWithRole:desc launchPos:spawn_pos rfactor:0.0];
2756 [vis setPosition:pos];
2757 [vis setOrientation:OORandomQuaternion()];
2759 success = [
self addEntity:vis];
2769- (
ShipEntity *) addShipAt:(HPVector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius
2774 if (radius == NSNotFound)
2776 GLfloat scalar = 1.0;
2777 [
self coordinatesForPosition:pos withCoordinateSystem:@"abs" returningScalar:&scalar];
2779 GLfloat rfactor = scalar;
2793 ShipEntity *ship = [
self newShipWithRole:role];
2799 if ([ship hasRole:
@"cargopod"]) [
self fillCargopodWithRandomCargo:ship];
2801 if (scanClass == CLASS_NOT_SET)
2803 scanClass = CLASS_NEUTRAL;
2807 if ([ship crew] ==
nil && ![ship isUnpiloted])
2809 [ship
setCrew:[NSArray arrayWithObject:
2816 BOOL trader = [role isEqualToString:@"trader"];
2826 if (pendingEscortCount > 0)
2828 OOGovernmentID government = [[
self currentSystemData] oo_unsignedCharForKey:KEY_GOVERNMENT];
2829 if ((
Ranrot() % 7) < government)
2831 int nx = pendingEscortCount - 2 * (1 + (
Ranrot() & 3));
2832 [ship setPendingEscortCount:(nx > 0) ? nx : 0];
2840 success = [
self addEntity:ship];
2847 if ([ship hasRole:
@"sunskim-trader"] &&
randf() < 0.25)
2850 [
self makeSunSkimmer:ship andSetAI:YES];
2857 else if ([role isEqual:
@"pirate"])
2859 [ship
setBounty:(Ranrot() & 7) + (Ranrot() & 7) + ((randf() < 0.05)? 63 : 23)
withReason:kOOLegalStatusReasonSetup];
2876- (NSArray *) addShipsAt:(HPVector)pos withRole:(NSString *)role quantity:(
unsigned)count withinRadius:(GLfloat)radius asGroup:(BOOL)isGroup
2880 NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
2891 ship = [
self addShipAt:pos withRole:role withinRadius:radius];
2895 if (isGroup) [ship
setGroup:group];
2896 [ships addObject:ship];
2900 if ([ships
count] == 0)
return nil;
2902 return [[ships copy] autorelease];
2908- (NSArray *) addShipsToRoute:(NSString *)route withRole:(NSString *)role quantity:(
unsigned)count routeFraction:(
double)routeFraction asGroup:(BOOL)isGroup
2910 NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
2916 if ([route isEqualToString:
@"pw"] || [route isEqualToString:
@"sw"] || [route isEqualToString:
@"ps"])
2918 routeFraction = 1.0f - routeFraction;
2922 if ([route isEqualTo:
@"wp"] || [route isEqualTo:
@"pw"])
2924 point0 = [
self getWitchspaceExitPosition];
2925 entity = [
self planet];
2926 if (entity ==
nil)
return nil;
2928 radius = [entity radius];
2930 else if ([route isEqualTo:
@"ws"] || [route isEqualTo:
@"sw"])
2932 point0 = [
self getWitchspaceExitPosition];
2933 entity = [
self sun];
2934 if (entity ==
nil)
return nil;
2936 radius = [entity radius];
2938 else if ([route isEqualTo:
@"sp"] || [route isEqualTo:
@"ps"])
2940 entity = [
self sun];
2941 if (entity ==
nil)
return nil;
2943 double radius0 = [entity radius];
2945 entity = [
self planet];
2946 if (entity ==
nil)
return nil;
2948 radius = [entity radius];
2951 direction = HPvector_normal(HPvector_subtract(point0, point1));
2952 point0 = HPvector_subtract(point0, HPvector_multiply_scalar(direction, radius0 +
SCANNER_MAX_RANGE * 1.1f));
2954 else if ([route isEqualTo:
@"st"])
2956 point0 = [
self getWitchspaceExitPosition];
2957 if ([
self station] ==
nil)
return nil;
2958 point1 = [[
self station] position];
2959 radius = [[
self station] collisionRadius];
2964 direction = HPvector_normal(HPvector_subtract(point1, point0));
2965 point1 = HPvector_subtract(point1, HPvector_multiply_scalar(direction, radius +
SCANNER_MAX_RANGE * 1.1f));
2967 pos = [
self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
2970 return [
self addShipsAt:pos withRole:role quantity:count withinRadius:(SCANNER_MAX_RANGE / 10.0f) asGroup:YES];
2976 ship = [
self addShipAt:pos withRole:role withinRadius:0];
2977 if (ship !=
nil) [ships addObject:ship];
2978 if (
count > 0) pos = [
self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
2981 if ([ships
count] == 0)
return nil;
2984 return [[ships copy] autorelease];
2988- (BOOL) roleIsPirateVictim:(NSString *)role
2990 return [
self role:role isInCategory:@"oolite-pirate-victim"];
2994- (BOOL) role:(NSString *)role isInCategory:(NSString *)category
2996 NSSet *categoryInfo = [roleCategories objectForKey:category];
2997 if (categoryInfo ==
nil)
3001 return [categoryInfo containsObject:role];
3006- (void) forceWitchspaceEntries
3009 for (i = 0; i < n_entities; i++)
3011 if (sortedEntities[i]->isShip)
3015 if ([my_target isWormhole])
3019 else if ([[[my_ship getAI] state] isEqualToString:
@"ENTER_WORMHOLE"])
3028- (void) addWitchspaceJumpEffectForShip:(
ShipEntity *)ship
3031 if ([
PLAYER status] != STATUS_ENTERING_WITCHSPACE && [
PLAYER status] != STATUS_EXITING_WITCHSPACE)
3039- (GLfloat) safeWitchspaceExitDistance
3041 for (
unsigned i = 0; i < n_entities; i++)
3043 Entity *e2 = sortedEntities[i];
3044 if ([e2 isShip] && [(
ShipEntity*)e2 hasPrimaryRole:
@"buoy-witchpoint"])
3053- (void) setUpBreakPattern:(HPVector) pos orientation:(Quaternion) q forDocking:(BOOL) forDocking
3060 [
self setViewDirection:VIEW_FORWARD];
3072 colorDesc = [[
self globalSettings] objectForKey:@"hyperspace_tunnel_color_1"];
3073 if (colorDesc !=
nil)
3076 if (color !=
nil) col1 = color;
3077 else OOLogWARN(
@"hyperspaceTunnel.fromDict",
@"could not interpret \"%@\
" as a colour.", colorDesc);
3080 colorDesc = [[
self globalSettings] objectForKey:@"hyperspace_tunnel_color_2"];
3081 if (colorDesc !=
nil)
3084 if (color !=
nil) col2 = color;
3085 else OOLogWARN(
@"hyperspaceTunnel.fromDict",
@"could not interpret \"%@\
" as a colour.", colorDesc);
3089 GLfloat startAngle = 0;
3090 GLfloat aspectRatio = 1;
3094 NSDictionary *info = [[PLAYER dockedStation] shipInfoDictionary];
3095 sides = [info oo_unsignedIntForKey:@"tunnel_corners" defaultValue:4];
3096 startAngle = [info oo_floatForKey:@"tunnel_start_angle" defaultValue:45.0f];
3097 aspectRatio = [info oo_floatForKey:@"tunnel_aspect_ratio" defaultValue:2.67f];
3100 for (i = 1; i < 11; i++)
3109 [ring
setPosition:HPvector_add(pos, vectorToHPVector(offset))];
3112 [ring
setLifetime:i * BREAK_PATTERN_RING_SPACING];
3116 if (forDocking && ![[
PLAYER dockedStation] hasBreakPattern])
3120 else if (!forDocking && ![
self witchspaceBreakPattern])
3124 [
self addEntity:ring];
3125 breakPatternCounter++;
3130- (BOOL) witchspaceBreakPattern
3132 return _witchspaceBreakPattern;
3136- (void) setWitchspaceBreakPattern:(BOOL)newValue
3138 _witchspaceBreakPattern = !!newValue;
3142- (BOOL) dockingClearanceProtocolActive
3144 return _dockingClearanceProtocolActive;
3148- (void) setDockingClearanceProtocolActive:(BOOL)newValue
3151 NSEnumerator *statEnum = [allStations objectEnumerator];
3159 while ((station = [statEnum nextObject]))
3162 if (![[[registry shipInfoForKey:stationKey] allKeys] containsObject:
@"requires_docking_clearance"])
3168 _dockingClearanceProtocolActive = !!newValue;
3172- (void) handleGameOver
3174 if ([[
self gameController] playerFileToLoad])
3176 [[
self gameController] loadPlayerIfRequired];
3180 [
self setUseAddOns:SCENARIO_OXP_DEFINITION_ALL fromSaveGame:NO forceReinit:YES];
3185- (void) setupIntroFirstGo:(BOOL)justCobra
3189 Quaternion q2 = { 0.0f, 0.0f, 1.0f, 0.0f };
3197 [
self removeDemoShips];
3209 ship = [
self newShipWithName:PLAYER_SHIP_DESC usePlayerProxy:YES];
3215 demo_ship_index = 0;
3216 demo_ship_subindex = 0;
3220 NSArray *subList =
nil;
3221 foreach (subList, demo_ships)
3223 if ([[[subList oo_dictionaryAtIndex:0] oo_stringForKey:
kOODemoShipClass] isEqualToString:
@"ship"])
3225 demo_ship_index = [demo_ships indexOfObject:subList];
3226 NSDictionary *shipEntry =
nil;
3227 foreach (shipEntry, subList)
3229 if ([[shipEntry oo_stringForKey:
kOODemoShipKey] isEqualToString:
@"cobra3-trader"])
3231 demo_ship_subindex = [subList indexOfObject:shipEntry];
3240 if (!demo_ship) ship = [
self newShipWithName:[[[demo_ships oo_arrayAtIndex:demo_ship_index] oo_dictionaryAtIndex:demo_ship_subindex] oo_stringForKey:kOODemoShipKey] usePlayerProxy:NO];
3251 [ship
setPositionX:0.0f
y:0.0f
z:DEMO2_VANISHING_DISTANCE * ship->collision_radius * 0.01];
3264 [
self addEntity:ship];
3266 [ship
setStatus:STATUS_COCKPIT_DISPLAY];
3275 [
self setLibraryTextForDemoShip];
3278 [
self enterGUIViewModeWithMouseInteraction:NO];
3282 demo_stage_time = universal_time + 300.0;
3289 return [[demo_ships oo_arrayAtIndex:demo_ship_index] oo_dictionaryAtIndex:demo_ship_subindex];
3299 [gui setTabStops:tab_stops];
3304 NSDictionary *librarySettings = [
self demoShipData];
3308 NSString *field1 =
nil;
3309 NSString *field2 =
nil;
3310 NSString *field3 =
nil;
3311 NSString *
override =
nil;
3314 for (NSUInteger i=1;i<=26;i++)
3316 [gui setText:@"" forRow:i];
3320 override = [librarySettings oo_stringForKey:kOODemoShipClass defaultValue:@"ship"];
3324 field2 = [demo_ship shipClassName];
3327 override = [librarySettings oo_stringForKey:kOODemoShipSummary defaultValue:nil];
3328 if (
override !=
nil)
3336 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:1];
3348 override = [librarySettings oo_stringForKey:kOODemoShipSpeed defaultValue:nil];
3349 if (
override !=
nil)
3351 if ([
override length] == 0)
3357 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-speed-custom"),OOExpand(override)];
3366 override = [librarySettings oo_stringForKey:kOODemoShipTurnRate defaultValue:nil];
3367 if (
override !=
nil)
3369 if ([
override length] == 0)
3375 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-turn-custom"),OOExpand(override)];
3384 override = [librarySettings oo_stringForKey:kOODemoShipCargo defaultValue:nil];
3385 if (
override !=
nil)
3387 if ([
override length] == 0)
3393 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-cargo-custom"),OOExpand(override)];
3402 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:3];
3405 override = [librarySettings oo_stringForKey:kOODemoShipGenerator defaultValue:nil];
3406 if (
override !=
nil)
3408 if ([
override length] == 0)
3414 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-generator-custom"),OOExpand(override)];
3423 override = [librarySettings oo_stringForKey:kOODemoShipShields defaultValue:nil];
3424 if (
override !=
nil)
3426 if ([
override length] == 0)
3432 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-shields-custom"),OOExpand(override)];
3441 override = [librarySettings oo_stringForKey:kOODemoShipWitchspace defaultValue:nil];
3442 if (
override !=
nil)
3444 if ([
override length] == 0)
3450 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-witchspace-custom"),OOExpand(override)];
3459 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:4];
3463 override = [librarySettings oo_stringForKey:kOODemoShipWeapons defaultValue:nil];
3464 if (
override !=
nil)
3466 if ([
override length] == 0)
3472 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-weapons-custom"),OOExpand(override)];
3480 override = [librarySettings oo_stringForKey:kOODemoShipTurrets defaultValue:nil];
3481 if (
override !=
nil)
3483 if ([
override length] == 0)
3489 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-turrets-custom"),OOExpand(override)];
3497 override = [librarySettings oo_stringForKey:kOODemoShipSize defaultValue:nil];
3498 if (
override !=
nil)
3500 if ([
override length] == 0)
3506 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-size-custom"),OOExpand(override)];
3514 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:5];
3517 override = [librarySettings oo_stringForKey:kOODemoShipDescription defaultValue:nil];
3518 if (
override !=
nil)
3520 [gui addLongText:OOExpand(override) startingAtRow:descRow align:GUI_ALIGN_LEFT];
3525 field1 = [NSString stringWithFormat:@"<-- %@",OOShipLibraryCategoryPlural([[[demo_ships objectAtIndex:((demo_ship_index+[demo_ships count]-1)%[demo_ships count])] objectAtIndex:0] oo_stringForKey:kOODemoShipClass])];
3527 field3 = [NSString stringWithFormat:@"%@ -->",OOShipLibraryCategoryPlural([[[demo_ships objectAtIndex:((demo_ship_index+1)%[demo_ships count])] objectAtIndex:0] oo_stringForKey:kOODemoShipClass])];
3529 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:19];
3533 NSArray *subList = [demo_ships objectAtIndex:demo_ship_index];
3534 NSUInteger i,start = demo_ship_subindex - (demo_ship_subindex%5);
3535 NSUInteger end = start + 4;
3536 if (end >= [subList
count])
3538 end = [subList count] - 1;
3543 for (i = start ; i <= end ; i++)
3545 field2 = [[subList objectAtIndex:i] oo_stringForKey:kOODemoShipName];
3546 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:row];
3547 if (i == demo_ship_subindex)
3561 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:20];
3564 if (end < [subList
count]-1)
3566 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:26];
3573- (void) selectIntro2Previous
3576 NSUInteger subcount = [[demo_ships objectAtIndex:demo_ship_index] count];
3577 demo_ship_subindex = (demo_ship_subindex + subcount - 2) % subcount;
3578 demo_stage_time = universal_time - 1.0;
3582- (void) selectIntro2PreviousCategory
3585 demo_ship_index = (demo_ship_index + [demo_ships
count] - 1) % [demo_ships
count];
3586 demo_ship_subindex = [[demo_ships objectAtIndex:demo_ship_index] count] - 1;
3587 demo_stage_time = universal_time - 1.0;
3591- (void) selectIntro2NextCategory
3594 demo_ship_index = (demo_ship_index + 1) % [demo_ships
count];
3595 demo_ship_subindex = [[demo_ships objectAtIndex:demo_ship_index] count] - 1;
3596 demo_stage_time = universal_time - 1.0;
3600- (void) selectIntro2Next
3603 demo_stage_time = universal_time - 1.0;
3613static BOOL IsFriendlyStationPredicate(
Entity *entity,
void *parameter)
3621 if (cachedSun !=
nil && cachedStation ==
nil)
3623 cachedStation = [
self findOneEntityMatchingPredicate:IsCandidateMainStationPredicate
3626 return cachedStation;
3630- (
StationEntity *) stationWithRole:(NSString *)role andPosition:(HPVector)position
3632 if ([role isEqualToString:
@""])
3637 float range = 1000000;
3639 NSArray *stations = [
self stations];
3641 foreach (station, stations)
3643 if (HPdistance2(position,[station position]) < range)
3645 if ([[station primaryRole] isEqualToString:role])
3659 return [
self findOneEntityMatchingPredicate:IsFriendlyStationPredicate parameter:ship];
3663- (OOPlanetEntity *) planet
3665 if (cachedPlanet ==
nil && [allPlanets
count] > 0)
3667 cachedPlanet = [allPlanets objectAtIndex:0];
3669 return cachedPlanet;
3675 if (cachedSun ==
nil)
3677 cachedSun = [
self findOneEntityMatchingPredicate:IsSunPredicate parameter:nil];
3683- (NSArray *) planets
3689- (NSArray *) stations
3691 return [allStations allObjects];
3695- (NSArray *) wormholes
3697 return activeWormholes;
3701- (void) unMagicMainStation
3713 if (playerStatus == STATUS_START_GAME)
return;
3717 cachedStation =
nil;
3721- (void) resetBeacons
3723 Entity <OOBeaconEntity> *beaconShip = [
self firstBeacon], *next =
nil;
3726 next = [beaconShip nextBeacon];
3727 [beaconShip setPrevBeacon:nil];
3728 [beaconShip setNextBeacon:nil];
3732 [
self setFirstBeacon:nil];
3733 [
self setLastBeacon:nil];
3737- (
Entity <OOBeaconEntity> *) firstBeacon
3739 return [_firstBeacon weakRefUnderlyingObject];
3743- (void) setFirstBeacon:(
Entity <OOBeaconEntity> *)beacon
3745 if (beacon != [
self firstBeacon])
3747 [beacon setPrevBeacon:nil];
3748 [beacon setNextBeacon:[
self firstBeacon]];
3749 [[
self firstBeacon] setPrevBeacon:beacon];
3750 [_firstBeacon release];
3751 _firstBeacon = [beacon weakRetain];
3756- (
Entity <OOBeaconEntity> *) lastBeacon
3758 return [_lastBeacon weakRefUnderlyingObject];
3762- (void) setLastBeacon:(
Entity <OOBeaconEntity> *)beacon
3764 if (beacon != [
self lastBeacon])
3766 [beacon setNextBeacon:nil];
3767 [beacon setPrevBeacon:[
self lastBeacon]];
3768 [[
self lastBeacon] setNextBeacon:beacon];
3769 [_lastBeacon release];
3770 _lastBeacon = [beacon weakRetain];
3775- (void) setNextBeacon:(
Entity <OOBeaconEntity> *) beaconShip
3777 if ([beaconShip isBeacon])
3779 [
self setLastBeacon:beaconShip];
3780 if ([
self firstBeacon] ==
nil) [
self setFirstBeacon:beaconShip];
3784 OOLog(
@"universe.beacon.error",
@"***** ERROR: Universe setNextBeacon '%@'. The ship has no beacon code set.", beaconShip);
3789- (void) clearBeacon:(
Entity <OOBeaconEntity> *) beaconShip
3791 Entity <OOBeaconEntity> *tmp =
nil;
3793 if ([beaconShip isBeacon])
3795 if ([
self firstBeacon] == beaconShip)
3797 tmp = [[beaconShip nextBeacon] nextBeacon];
3798 [
self setFirstBeacon:[beaconShip nextBeacon]];
3799 [[beaconShip prevBeacon] setNextBeacon:tmp];
3801 else if ([
self lastBeacon] == beaconShip)
3803 tmp = [[beaconShip prevBeacon] prevBeacon];
3804 [
self setLastBeacon:[beaconShip prevBeacon]];
3805 [[beaconShip nextBeacon] setPrevBeacon:tmp];
3809 [[beaconShip nextBeacon] setPrevBeacon:[beaconShip prevBeacon]];
3810 [[beaconShip prevBeacon] setNextBeacon:[beaconShip nextBeacon]];
3812 [beaconShip setBeaconCode:nil];
3817- (NSDictionary *) currentWaypoints
3823- (void) defineWaypoint:(NSDictionary *)definition forKey:(NSString *)key
3826 BOOL preserveCompass = NO;
3827 waypoint = [waypoints objectForKey:key];
3828 if (waypoint !=
nil)
3830 if ([
PLAYER compassTarget] == waypoint)
3832 preserveCompass = YES;
3834 [
self removeEntity:waypoint];
3835 [waypoints removeObjectForKey:key];
3837 if (definition !=
nil)
3840 if (waypoint !=
nil)
3842 [
self addEntity:waypoint];
3843 [waypoints setObject:waypoint forKey:key];
3844 if (preserveCompass)
3846 [PLAYER setCompassTarget:waypoint];
3847 [PLAYER setNextBeacon:waypoint];
3854- (GLfloat *) skyClearColor
3856 return skyClearColor;
3860- (void) setSkyColorRed:(GLfloat)red green:(GLfloat)green blue:(GLfloat)blue alpha:(GLfloat)alpha
3862 skyClearColor[0] = red;
3863 skyClearColor[1] = green;
3864 skyClearColor[2] = blue;
3865 skyClearColor[3] = alpha;
3866 [
self setAirResistanceFactor:alpha];
3870- (BOOL) breakPatternOver
3872 return (breakPatternCounter == 0);
3876- (BOOL) breakPatternHide
3879 return ((breakPatternCounter > 5)||(!player)||([player status] == STATUS_DOCKING));
3883#define PROFILE_SHIP_SELECTION 0
3886- (BOOL) canInstantiateShip:(NSString *)shipKey
3888 NSDictionary *shipInfo =
nil;
3889 NSArray *conditions =
nil;
3890 NSString *condition_script =
nil;
3893 condition_script = [shipInfo oo_stringForKey:@"condition_script"];
3894 if (condition_script !=
nil)
3896 OOJSScript *condScript = [
self getConditionScript:condition_script];
3897 if (condScript !=
nil)
3901 JSBool allow_instantiation;
3905 OK = [condScript
callMethod:OOJSID("allowSpawnShip")
3910 if (OK) OK = JS_ValueToBoolean(context, result, &allow_instantiation);
3914 if (OK && !allow_instantiation)
3924 conditions = [shipInfo oo_arrayForKey:@"conditions"];
3925 if (conditions ==
nil)
return YES;
3928 return [PLAYER scriptTestConditions:conditions];
3932- (NSString *) randomShipKeyForRoleRespectingConditions:(NSString *)role
3937 NSString *shipKey =
nil;
3940#if PROFILE_SHIP_SELECTION
3941 static unsigned long profTotal = 0, profSlowPath = 0;
3946 shipKey = [registry randomShipKeyForRole:role];
3947 if ([
self canInstantiateShip:shipKey]) return shipKey;
3956#if PROFILE_SHIP_SELECTION
3958 if ((profSlowPath % 10) == 0)
3960 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);
3964 pset = [[[registry probabilitySetForRole:role] mutableCopy] autorelease];
3966 while ([pset
count] > 0)
3970 if ([
self canInstantiateShip:shipKey]) return shipKey;
3983- (
ShipEntity *) newShipWithRole:(NSString *)role
3988 NSString *shipKey =
nil;
3989 NSDictionary *shipInfo =
nil;
3990 NSString *autoAI =
nil;
3992 shipKey = [
self randomShipKeyForRoleRespectingConditions:role];
3995 ship = [
self newShipWithName:shipKey];
3998 [ship setPrimaryRole:role];
4001 if ([shipInfo oo_fuzzyBooleanForKey:
@"auto_ai" defaultValue:YES])
4004 autoAI = [
self defaultAIForRole:role];
4007 [ship setAITo:autoAI];
4010 if ([role isEqualToString:
@"pirate"]) [ship setBounty:20 +
randf() * 50 withReason:kOOLegalStatusReasonSetup];
4011 if ([role isEqualToString:
@"trader"]) [ship setBounty:0 withReason:kOOLegalStatusReasonSetup];
4012 if ([role isEqualToString:
@"police"]) [ship setScanClass:CLASS_POLICE];
4013 if ([role isEqualToString:
@"interceptor"])
4015 [ship setScanClass: CLASS_POLICE];
4016 [ship setPrimaryRole:@"police"];
4019 if ([role isEqualToString:
@"thargoid"]) [ship setScanClass: CLASS_THARGOID];
4034 NSDictionary *effectDict =
nil;
4038 if (effectDict ==
nil)
return nil;
4044 @catch (NSException *exception)
4048 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newVisualEffectWithName: %@ ] *****", [exception reason], effectKey);
4050 else @throw exception;
4059- (
ShipEntity *) newSubentityWithName:(NSString *)shipKey andScaleFactor:(
float)scale
4061 return [
self newShipWithName:shipKey usePlayerProxy:NO isSubentity:YES andScaleFactor:scale];
4065- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy
4067 return [
self newShipWithName:shipKey usePlayerProxy:usePlayerProxy isSubentity:NO];
4070- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy isSubentity:(BOOL)isSubentity
4072 return [
self newShipWithName:shipKey usePlayerProxy:usePlayerProxy isSubentity:isSubentity andScaleFactor:1.0f];
4075- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy isSubentity:(BOOL)isSubentity andScaleFactor:(
float)scale
4079 NSDictionary *shipDict =
nil;
4083 if (shipDict ==
nil)
return nil;
4085 volatile Class shipClass =
nil;
4092 shipClass = [
self shipClassForShipDictionary:shipDict];
4093 if (usePlayerProxy && shipClass == [
ShipEntity class])
4103 NSMutableDictionary *mShipDict = [shipDict mutableCopy];
4104 [mShipDict setObject:[NSNumber numberWithFloat:scale] forKey:@"model_scale_factor"];
4105 shipDict = [NSDictionary dictionaryWithDictionary:mShipDict];
4106 [mShipDict release];
4108 ship = [[shipClass alloc] initWithKey:shipKey definition:shipDict];
4110 @catch (NSException *exception)
4114 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newShipWithName: %@ ] *****", [exception reason], shipKey);
4116 else @throw exception;
4121 if ([ship hasRole:shipKey]) [ship setPrimaryRole:shipKey];
4129- (
DockEntity *) newDockWithName:(NSString *)shipDataKey andScaleFactor:(
float)scale
4133 NSDictionary *shipDict =
nil;
4137 if (shipDict ==
nil)
return nil;
4143 NSMutableDictionary *mShipDict = [shipDict mutableCopy];
4144 [mShipDict setObject:[NSNumber numberWithFloat:scale] forKey:@"model_scale_factor"];
4145 shipDict = [NSDictionary dictionaryWithDictionary:mShipDict];
4146 [mShipDict release];
4148 dock = [[
DockEntity alloc] initWithKey:shipDataKey definition:shipDict];
4150 @catch (NSException *exception)
4154 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newDockWithName: %@ ] *****", [exception reason], shipDataKey);
4156 else @throw exception;
4161 if ([dock hasRole:shipDataKey]) [dock setPrimaryRole:shipDataKey];
4169- (
ShipEntity *) newShipWithName:(NSString *)shipKey
4171 return [
self newShipWithName:shipKey usePlayerProxy:NO];
4175- (Class) shipClassForShipDictionary:(NSDictionary *)dict
4179 if (dict ==
nil)
return Nil;
4181 BOOL isStation = NO;
4182 NSString *shipRoles = [dict oo_stringForKey:@"roles"];
4184 if (shipRoles !=
nil)
4186 isStation = [shipRoles rangeOfString:@"station"].location != NSNotFound ||
4187 [shipRoles rangeOfString:@"carrier"].location != NSNotFound;
4191 isStation = [dict oo_boolForKey:@"isCarrier" defaultValue:isStation];
4192 isStation = [dict oo_boolForKey:@"is_carrier" defaultValue:isStation];
4201- (NSString *)defaultAIForRole:(NSString *)role
4203 return [autoAIMap oo_stringForKey:role];
4218 foreach (itemData, equipmentData)
4220 NSString *itemType = [itemData oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
4222 if ([itemType isEqual:eq_key])
4224 return [itemData oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
4240 if ([cargoObj isTemplateCargoPod])
4242 return [UNIVERSE cargoPodFromTemplate:cargoObj];
4256 OOCargoQuantity co_amount = [UNIVERSE getRandomAmountOfCommodity:co_type];
4259 container = [UNIVERSE newShipWithRole:co_type];
4261 if (container ==
nil)
4263 container = [UNIVERSE newShipWithRole:@"cargopod"];
4266 return [container autorelease];
4270- (NSArray *) getContainersOfGoods:(
OOCargoQuantity)how_many scarce:(BOOL)scarce legal:(BOOL)legal
4276 NSMutableArray *accumulator = [NSMutableArray arrayWithCapacity:how_many];
4277 NSUInteger i=0, commodityCount = [commodityMarket count];
4281 NSArray *goodsKeys = [commodityMarket goods];
4282 NSString *goodsKey =
nil;
4284 foreach (goodsKey, goodsKeys)
4289 if (q < 64) q = 64 - q;
4294 if (legal && [commodityMarket exportLegalityForGood:goodsKey] > 0)
4300 quantities[i++] = q;
4301 total_quantity += q;
4304 for (i = 0; i < how_many; i++)
4306 NSUInteger co_type = 0;
4311 qr = 1+(
Ranrot() % total_quantity);
4315 NSAssert((NSUInteger)co_type < commodityCount,
@"Commodity type index out of range.");
4316 qr -= quantities[co_type++];
4321 ShipEntity *container = [cargoPods objectForKey:[goodsKeys oo_stringAtIndex:co_type]];
4323 if (container !=
nil)
4325 [accumulator addObject:container];
4329 OOLog(
@"universe.createContainer.failed",
@"***** ERROR: failed to find a container to fill with %@ (%ld).", [goodsKeys oo_stringAtIndex:co_type], co_type);
4333 return [NSArray arrayWithArray:accumulator];
4339 NSMutableArray *accumulator = [NSMutableArray arrayWithCapacity:how_much];
4340 if (![commodities goodDefined:commodity_name])
4342 return [NSArray array];
4345 ShipEntity *container = [cargoPods objectForKey:commodity_name];
4346 while (how_much > 0)
4350 [accumulator addObject:container];
4354 OOLog(
@"universe.createContainer.failed",
@"***** ERROR: failed to find a container to fill with %@", commodity_name);
4359 return [NSArray arrayWithArray:accumulator];
4363- (void) fillCargopodWithRandomCargo:(
ShipEntity *)cargopod
4365 if (cargopod ==
nil || ![cargopod hasRole:
@"cargopod"] || [cargopod cargoType] ==
CARGO_SCRIPTED_ITEM) return;
4367 if ([cargopod commodityType] ==
nil || ![cargopod commodityAmount])
4369 NSString *aCommodity = [
self getRandomCommodity];
4370 OOCargoQuantity aQuantity = [
self getRandomAmountOfCommodity:aCommodity];
4376- (NSString *) getRandomCommodity
4378 return [commodities getRandomCommodity];
4386 if (co_type ==
nil) {
4390 units = [commodities massUnitForGood:co_type];
4400 OOLog(
@"universe.commodityAmount.warning",
@"Commodity %@ has an unrecognised mass unit, assuming tonnes",co_type);
4407 return [commodityMarket definitionForGood:type];
4413 return [commodityMarket nameForGood:co_type];
4420 NSString *unitDesc =
nil, *typeDesc =
nil;
4421 NSDictionary *commodity = [
self commodityDataForType:co_type];
4423 if (commodity ==
nil)
return @"";
4425 units = [commodityMarket massUnitForGood:co_type];
4431 unitDesc =
DESC(
@"cargo-kilogram");
4434 unitDesc =
DESC(
@"cargo-gram");
4438 unitDesc =
DESC(
@"cargo-ton");
4447 unitDesc =
DESC(
@"cargo-kilograms");
4450 unitDesc =
DESC(
@"cargo-grams");
4454 unitDesc =
DESC(
@"cargo-tons");
4459 typeDesc = [commodityMarket nameForGood:co_type];
4461 return [NSString stringWithFormat:@"%d %@ %@",co_amount, unitDesc, typeDesc];
4469 gameView = [view retain];
4481 return [[
self gameView] gameController];
4485- (NSDictionary *) gameSettings
4488 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:11];
4490 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:10];
4493 [result oo_setInteger:[PLAYER isSpeechOn] forKey:@"speechOn"];
4494 [result oo_setBool:autoSave forKey:@"autosave"];
4495 [result oo_setBool:wireframeGraphics forKey:@"wireframeGraphics"];
4496 [result oo_setBool:doProcedurallyTexturedPlanets forKey:@"procedurallyTexturedPlanets"];
4498 [result oo_setFloat:[gameView gammaValue] forKey:@"gammaValue"];
4501 [result oo_setFloat:[gameView fov:NO] forKey:@"fovValue"];
4504 if ([gameView hdrOutput])
4506 [result oo_setFloat:[gameView hdrMaxBrightness] forKey:@"hdr-max-brightness"];
4507 [result oo_setFloat:[gameView hdrPaperWhiteBrightness] forKey:@"hdr-paperwhite-brightness"];
4511 [result setObject:OOStringFromGraphicsDetail([
self detailLevel]) forKey:@"detailLevel"];
4513 NSString *desc =
@"UNDEFINED";
4520 [result setObject:desc forKey:@"musicMode"];
4522 NSDictionary *gameWindow = [NSDictionary dictionaryWithObjectsAndKeys:
4523 [NSNumber numberWithFloat:[gameView viewSize].width], @"width",
4524 [NSNumber numberWithFloat:[gameView viewSize].height], @"height",
4525 [NSNumber numberWithBool:[[
self gameController] inFullScreenMode]], @"fullScreen",
4527 [result setObject:gameWindow forKey:@"gameWindow"];
4529 [result setObject:[PLAYER keyConfig] forKey:@"keyConfig"];
4531 return [[result copy] autorelease];
4535- (void) useGUILightSource:(BOOL)GUILight
4539 if (![
self useShaders])
4543 OOGL(glEnable(GL_LIGHT0));
4544 OOGL(glDisable(GL_LIGHT1));
4548 OOGL(glEnable(GL_LIGHT1));
4549 OOGL(glDisable(GL_LIGHT0));
4558 else OOGL(glEnable(GL_LIGHT1));
4565- (void) lightForEntity:(BOOL)isLit
4569 if ([
self useShaders])
4573 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
4574 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
4586 if (isLit)
OOGL(glEnable(GL_LIGHT1));
4587 else OOGL(glDisable(GL_LIGHT1));
4592 OOGL(glEnable(GL_LIGHT0));
4608 { 1.0f, 0.0f, 0.0f, 0.0f },
4609 { 0.0f, 1.0f, 0.0f, 0.0f },
4610 { 0.0f, 0.0f, 1.0f, 0.0f },
4611 { 0.0f, 0.0f, 0.0f, 1.0f }
4615 {-1.0f, 0.0f, 0.0f, 0.0f },
4616 { 0.0f, 1.0f, 0.0f, 0.0f },
4617 { 0.0f, 0.0f, -1.0f, 0.0f },
4618 { 0.0f, 0.0f, 0.0f, 1.0f }
4622 { 0.0f, 0.0f, -1.0f, 0.0f },
4623 { 0.0f, 1.0f, 0.0f, 0.0f },
4624 { 1.0f, 0.0f, 0.0f, 0.0f },
4625 { 0.0f, 0.0f, 0.0f, 1.0f }
4629 { 0.0f, 0.0f, 1.0f, 0.0f },
4630 { 0.0f, 1.0f, 0.0f, 0.0f },
4631 {-1.0f, 0.0f, 0.0f, 0.0f },
4632 { 0.0f, 0.0f, 0.0f, 1.0f }
4636- (void) getActiveViewMatrix:(OOMatrix *)outMatrix forwardVector:(Vector *)outForward upVector:(Vector *)outUp
4638 assert(outMatrix != NULL && outForward != NULL && outUp != NULL);
4642 switch (viewDirection)
4656 case VIEW_STARBOARD:
4671 case VIEW_GUI_DISPLAY:
4672 case VIEW_BREAK_PATTERN:
4682- (OOMatrix) activeViewMatrix
4687 [
self getActiveViewMatrix:&m forwardVector:&f upVector:&u];
4697- (void) defineFrustum
4705 frustum[0][0] = clip.m[0][3] - clip.m[0][0];
4706 frustum[0][1] = clip.m[1][3] - clip.m[1][0];
4707 frustum[0][2] = clip.m[2][3] - clip.m[2][0];
4708 frustum[0][3] = clip.m[3][3] - clip.m[3][0];
4711 rt = 1.0f / sqrt(frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2]);
4712 frustum[0][0] *= rt;
4713 frustum[0][1] *= rt;
4714 frustum[0][2] *= rt;
4715 frustum[0][3] *= rt;
4718 frustum[1][0] = clip.m[0][3] + clip.m[0][0];
4719 frustum[1][1] = clip.m[1][3] + clip.m[1][0];
4720 frustum[1][2] = clip.m[2][3] + clip.m[2][0];
4721 frustum[1][3] = clip.m[3][3] + clip.m[3][0];
4724 rt = 1.0f / sqrt(frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2]);
4725 frustum[1][0] *= rt;
4726 frustum[1][1] *= rt;
4727 frustum[1][2] *= rt;
4728 frustum[1][3] *= rt;
4731 frustum[2][0] = clip.m[0][3] + clip.m[0][1];
4732 frustum[2][1] = clip.m[1][3] + clip.m[1][1];
4733 frustum[2][2] = clip.m[2][3] + clip.m[2][1];
4734 frustum[2][3] = clip.m[3][3] + clip.m[3][1];
4737 rt = 1.0 / sqrt(frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2]);
4738 frustum[2][0] *= rt;
4739 frustum[2][1] *= rt;
4740 frustum[2][2] *= rt;
4741 frustum[2][3] *= rt;
4744 frustum[3][0] = clip.m[0][3] - clip.m[0][1];
4745 frustum[3][1] = clip.m[1][3] - clip.m[1][1];
4746 frustum[3][2] = clip.m[2][3] - clip.m[2][1];
4747 frustum[3][3] = clip.m[3][3] - clip.m[3][1];
4750 rt = 1.0 / sqrt(frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2]);
4751 frustum[3][0] *= rt;
4752 frustum[3][1] *= rt;
4753 frustum[3][2] *= rt;
4754 frustum[3][3] *= rt;
4757 frustum[4][0] = clip.m[0][3] - clip.m[0][2];
4758 frustum[4][1] = clip.m[1][3] - clip.m[1][2];
4759 frustum[4][2] = clip.m[2][3] - clip.m[2][2];
4760 frustum[4][3] = clip.m[3][3] - clip.m[3][2];
4763 rt = sqrt(frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2]);
4764 frustum[4][0] *= rt;
4765 frustum[4][1] *= rt;
4766 frustum[4][2] *= rt;
4767 frustum[4][3] *= rt;
4770 frustum[5][0] = clip.m[0][3] + clip.m[0][2];
4771 frustum[5][1] = clip.m[1][3] + clip.m[1][2];
4772 frustum[5][2] = clip.m[2][3] + clip.m[2][2];
4773 frustum[5][3] = clip.m[3][3] + clip.m[3][2];
4776 rt = sqrt(frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2]);
4777 frustum[5][0] *= rt;
4778 frustum[5][1] *= rt;
4779 frustum[5][2] *= rt;
4780 frustum[5][3] *= rt;
4784- (BOOL) viewFrustumIntersectsSphereAt:(Vector)position withRadius:(GLfloat)radius
4788 for (p = 0; p < 6; p++)
4790 if (frustum[p][0] * position.x + frustum[p][1] * position.y + frustum[p][2] * position.z + frustum[p][3] <= -radius)
4799- (void) drawUniverse
4801 int currentPostFX = [
self currentPostFX];
4803 NSSize viewSize = [gameView viewSize];
4804 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin draw");
4808 if ((
int)targetFramebufferSize.width != (
int)viewSize.width || (
int)targetFramebufferSize.height != (
int)viewSize.height)
4810 [
self resizeTargetFramebufferWithViewSize:viewSize];
4813 if([
self useShaders])
4815 if ([gameView msaa])
4817 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
4821 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
4828 int i, v_status, vdist;
4829 Vector view_dir, view_up;
4830 OOMatrix view_matrix;
4831 int ent_count = n_entities;
4832 Entity *my_entities[ent_count];
4838 float aspect = viewSize.height/viewSize.width;
4840 if (!displayGUI && wasDisplayGUI)
4843 if (cachedSun) [UNIVERSE setMainLightPosition:HPVectorToVector([cachedSun position])];
4844 else [UNIVERSE setMainLightPosition:kZeroVector];
4846 wasDisplayGUI = displayGUI;
4848 for (i = 0; i < ent_count; i++)
4855 Entity *e = sortedEntities[i];
4858 my_entities[draw_count++] = [[e retain] autorelease];
4862 v_status = [player
status];
4868 OOGL(glClear(GL_COLOR_BUFFER_BIT));
4872 OOGL(glClearColor(skyClearColor[0], skyClearColor[1], skyClearColor[2], skyClearColor[3]));
4876 OOGL(glClearColor(0.0, 0.0, 0.0, 0.0));
4880 [gui drawGUIBackground];
4884 BOOL fogging, bpHide = [
self breakPatternHide];
4886 for (vdist=0;vdist<=1;vdist++)
4890 float ratio = (displayGUI ? 0.5 : [gameView fov:YES]) * nearPlane;
4893 if ((displayGUI && 4*aspect >= 3) || (!displayGUI && 4*aspect <= 3))
4895 OOGLFrustum(-ratio, ratio, -aspect*ratio, aspect*ratio, nearPlane, farPlane);
4899 OOGLFrustum(-3*ratio/aspect/4, 3*ratio/aspect/4, -3*ratio/4, 3*ratio/4, nearPlane, farPlane);
4902 [
self getActiveViewMatrix:&view_matrix forwardVector:&view_dir upVector:&view_up];
4934 OOGL(glClear(GL_DEPTH_BUFFER_BIT));
4939 flipMatrix.m[2][2] = -1;
4945 if (
EXPECT(!displayGUI || demoShipMode))
4947 if (
EXPECT(!demoShipMode))
4953 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
4957 [
self setMainLightPosition:[cachedSun cameraRelativePosition]];
4962 [
self setMainLightPosition:HPVectorToVector(HPvector_flip([PLAYER viewpointPosition]))];
4964 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, main_light_position));
4970 OOGL(glLightfv(GL_LIGHT0, GL_POSITION, main_light_position));
4972 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, main_light_position));
4976 OOGL([
self useGUILightSource:demoShipMode]);
4981 int furthest = draw_count - 1;
4983 BOOL inAtmosphere = airResistanceFactor > 0.01;
4984 GLfloat fogFactor = 0.5 / airResistanceFactor;
4985 double fog_scale, half_scale;
4986 GLfloat flat_ambdiff[4] = {1.0, 1.0, 1.0, 1.0};
4987 GLfloat mat_no[4] = {0.0, 0.0, 0.0, 1.0};
4990 OOGL(glHint(GL_FOG_HINT, [
self reducedDetail] ? GL_FASTEST : GL_NICEST));
4992 [
self defineFrustum];
4996 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin opaque pass");
5000 for (i = furthest; i >= nearest; i--)
5002 drawthing = my_entities[i];
5006 if (vdist == 1 && [drawthing cameraRangeFront] > farPlane*1.5)
continue;
5007 if (vdist == 0 && [drawthing cameraRangeBack] < nearPlane)
continue;
5010 if (!((d_status == STATUS_COCKPIT_DISPLAY) ^ demoShipMode))
5014 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, flat_ambdiff));
5015 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_no));
5018 if (
EXPECT(drawthing != player))
5041 half_scale = fog_scale * 0.50;
5042 OOGL(glEnable(GL_FOG));
5043 OOGL(glFogi(GL_FOG_MODE, GL_LINEAR));
5044 OOGL(glFogfv(GL_FOG_COLOR, skyClearColor));
5045 OOGL(glFogf(GL_FOG_START, half_scale));
5046 OOGL(glFogf(GL_FOG_END, fog_scale));
5047 fog_blend = OOClamp_0_1_f((magnitude([drawthing cameraRelativePosition]) - half_scale)/half_scale);
5051 [
self lightForEntity:demoShipMode || drawthing->isSunlit];
5062 OOGL(glDisable(GL_FOG));
5067 if (!((d_status == STATUS_COCKPIT_DISPLAY) ^ demoShipMode))
5070 if (
EXPECT(drawthing != player))
5093 half_scale = fog_scale * 0.50;
5094 OOGL(glEnable(GL_FOG));
5095 OOGL(glFogi(GL_FOG_MODE, GL_LINEAR));
5096 OOGL(glFogfv(GL_FOG_COLOR, skyClearColor));
5097 OOGL(glFogf(GL_FOG_START, half_scale));
5098 OOGL(glFogf(GL_FOG_END, fog_scale));
5099 fog_blend = OOClamp_0_1_f((magnitude([drawthing cameraRelativePosition]) - half_scale)/half_scale);
5110 OOGL(glDisable(GL_FOG));
5127 if (!bpHide && cachedSun)
5129 [cachedSun drawDirectVisionSunGlare];
5130 [cachedSun drawStarGlare];
5135 if (hudSeparateRenderPass)
5140 [
self prepareToRenderIntoDefaultFramebuffer];
5141 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
5143 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"Begin second pass draw");
5144 [
self drawTargetTextureIntoDefaultFramebuffer];
5145 OOCheckOpenGLErrors(
@"Universe after drawing from custom framebuffer to screen framebuffer");
5146 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"End second pass drawing");
5148 OOLog(
@"universe.profile.drawHUD",
@"%@",
@"Begin HUD drawing");
5153 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin HUD");
5155 GLfloat lineWidth = [gameView viewSize].width / 1024.0;
5156 if (lineWidth < 1.0) lineWidth = 1.0;
5157 if (lineWidth > 1.5) lineWidth = 1.5;
5164 if ([theHUD deferredHudName] !=
nil)
5168 [deferredName release];
5169 theHUD = [player
hud];
5173 static float sPrevHudAlpha = -1.0f;
5174 if ([theHUD isHidden])
5176 if (sPrevHudAlpha < 0.0f)
5182 else if (sPrevHudAlpha >= 0.0f)
5185 sPrevHudAlpha = -1.0f;
5190 case STATUS_ESCAPE_SEQUENCE:
5191 case STATUS_START_GAME:
5195 switch ([player guiScreen])
5209#if (defined (SNAPSHOT_BUILD) && defined (OOLITE_SNAPSHOT_VERSION))
5210 [
self drawWatermarkString:@"Development version " @OOLITE_SNAPSHOT_VERSION];
5213 OOLog(
@"universe.profile.drawHUD",
@"%@",
@"End HUD drawing");
5222 if (![[
self gameController] isGamePaused])
5224 framesDoneThisUpdate++;
5227 @catch (NSException *exception)
5231 if ([[exception name] hasPrefix:
@"Oolite"])
5233 [
self handleOoliteException:exception];
5237 OOLog(
kOOLogException,
@"***** Exception: %@ : %@ *****",[exception name], [exception reason]);
5243 OOLog(
@"universe.profile.draw",
@"%@",
@"End drawing");
5246 if(!hudSeparateRenderPass)
5248 if([
self useShaders])
5250 [
self prepareToRenderIntoDefaultFramebuffer];
5251 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
5253 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"Begin second pass draw");
5254 [
self drawTargetTextureIntoDefaultFramebuffer];
5255 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"End second pass drawing");
5263 NSSize viewSize = [gameView viewSize];
5264 if([
self useShaders])
5266 if ([gameView msaa])
5269 OOGL(glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFramebufferID));
5270 OOGL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFramebufferID));
5271 OOGL(glBlitFramebuffer(0, 0, (GLint)viewSize.width, (GLint)viewSize.height, 0, 0, (GLint)viewSize.width, (GLint)viewSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
5277- (
int) framesDoneThisUpdate
5279 return framesDoneThisUpdate;
5283- (void) resetFramesDoneThisUpdate
5285 framesDoneThisUpdate = 0;
5289- (OOMatrix) viewMatrix
5299 OOGL(glDisable(GL_TEXTURE_2D));
5301 float overallAlpha = [[PLAYER hud] overallAlpha];
5306 cursor_row = [gui drawGUI:1.0 drawCursor:YES];
5310 [gui drawGUI:1.0 drawCursor:NO];
5314 [message_gui drawGUI:[message_gui alpha] * overallAlpha drawCursor:NO];
5315 [comm_log_gui drawGUI:[comm_log_gui alpha] * overallAlpha drawCursor:NO];
5321- (void) drawWatermarkString:(NSString *) watermarkString
5323 NSSize watermarkStringSize =
OORectFromString(watermarkString, 0.0f, 0.0f, NSMakeSize(10, 10)).size;
5325 OOGL(glColor4f(0.0, 1.0, 0.0, 1.0));
5339 OOLog(
@"universe.badUID",
@"Attempt to retrieve entity for out-of-range UID %u. (This is an internal programming error, please report it.)", u_id);
5343 if ((u_id ==
NO_TARGET)||(!entity_for_uid[u_id]))
5346 Entity *ent = entity_for_uid[u_id];
5352 if ([ent status] == STATUS_DEAD || [ent status] == STATUS_DOCKED)
5363 NSCParameterAssert(uni != NULL);
5376 while ((n--)&&(checkEnt))
5379 checkEnt = checkEnt->
x_next;
5381 if ((checkEnt)||(n > 0))
5389 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
x_previous;
5390 if ((checkEnt)||(n > 0))
5401 checkEnt = checkEnt->
x_next;
5409 while ((n--)&&(checkEnt))
5412 checkEnt = checkEnt->
y_next;
5414 if ((checkEnt)||(n > 0))
5422 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
y_previous;
5423 if ((checkEnt)||(n > 0))
5434 checkEnt = checkEnt->
y_next;
5442 while ((n--)&&(checkEnt))
5445 checkEnt = checkEnt->
z_next;
5447 if ((checkEnt)||(n > 0))
5455 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
z_previous;
5456 if ((checkEnt)||(n > 0))
5463 NSCAssert(checkEnt !=
nil,
@"Expected z-list to be non-empty.");
5468 checkEnt = checkEnt->
z_next;
5478 NSArray *allEntities = uni->
entities;
5484 foreach (ent, allEntities)
5500- (BOOL) addEntity:(
Entity *) entity
5508 if (![entity validForAddToUniverse])
return NO;
5511 if ([entities containsObject:entity])
5517 OOLog(
@"universe.addEntity.failed",
@"***** Universe cannot addEntity:%@ -- Universe is full (%d entities out of %d)", entity, n_entities,
UNIVERSE_MAX_ENTITIES);
5524 if (![entity isEffect])
5527 while (entity_for_uid[next_universal_id] !=
nil)
5529 next_universal_id++;
5537 OOLog(
@"universe.addEntity.failed",
@"***** Universe cannot addEntity:%@ -- Could not find free slot for entity.", entity);
5542 entity_for_uid[next_universal_id] = entity;
5543 if ([entity isShip])
5548 [
self setNextBeacon:se];
5555 double stationRoll = 0.0;
5559 if (definedRoll !=
nil)
5565 stationRoll = [[
self currentSystemData] oo_doubleForKey:@"station_roll" defaultValue:STANDARD_STATION_ROLL];
5578 if ([se status] != STATUS_COCKPIT_DISPLAY)
5587 if ([entity isVisualEffect])
5592 [
self setNextBeacon:ve];
5595 else if ([entity isWaypoint])
5600 [
self setNextBeacon:wp];
5610 [entities addObject:entity];
5614 HPVector entity_pos = entity->
position;
5615 HPVector delta = HPvector_between(entity_pos,
PLAYER->position);
5616 double z_distance = HPmagnitude2(delta);
5618 unsigned index = n_entities;
5619 sortedEntities[index] = entity;
5621 while ((index > 0)&&(z_distance < sortedEntities[index - 1]->zero_distance))
5623 sortedEntities[index] = sortedEntities[index - 1];
5624 sortedEntities[index]->zero_index = index;
5626 sortedEntities[index] = entity;
5635 if ([entity canCollide])
5637 doLinkedListMaintenanceThisUpdate = YES;
5640 if ([entity isWormhole])
5642 [activeWormholes addObject:entity];
5644 else if ([entity isPlanet])
5646 [allPlanets addObject:entity];
5648 else if ([entity isShip])
5652 if ([entity isStation])
5654 [allStations addObject:entity];
5664- (BOOL) removeEntity:(
Entity *) entity
5666 if (entity !=
nil && ![entity isPlayer])
5672 [entitiesDeadThisUpdate addObject:entity];
5673 if ([entity isStation])
5675 [allStations removeObject:entity];
5676 if ([
PLAYER getTargetDockStation] == entity)
5678 [PLAYER setDockingClearanceStatus:DOCKING_CLEARANCE_STATUS_NONE];
5681 return [
self doRemoveEntity:entity];
5687- (void) ensureEntityReallyRemoved:(
Entity *)entity
5691 OOLog(
@"universe.unremovedEntity",
@"Entity %@ dealloced without being removed from universe! (This is an internal programming error, please report it.)", entity);
5692 [
self doRemoveEntity:entity];
5697- (void) removeAllEntitiesExceptPlayer
5699 BOOL updating = no_update;
5703 Entity* p0 = [entities objectAtIndex:0];
5712 NSMutableArray *savedWormholes = [activeWormholes mutableCopy];
5714 while ([entities
count] > 1)
5716 Entity* ent = [entities objectAtIndex:1];
5719 if (
EXPECT(![ent isVisualEffect]))
5721 [
self removeEntity:ent];
5730 [activeWormholes release];
5731 activeWormholes = savedWormholes;
5738 cachedStation =
nil;
5739 [closeSystems release];
5742 [
self resetBeacons];
5743 [waypoints removeAllObjects];
5745 no_update = updating;
5749- (void) removeDemoShips
5752 int ent_count = n_entities;
5756 for (i = 0; i < ent_count; i++)
5758 ent = sortedEntities[i];
5759 if ([ent status] == STATUS_COCKPIT_DISPLAY && ![ent isPlayer])
5761 [
self removeEntity:ent];
5769- (
ShipEntity *) makeDemoShipWithRole:(NSString *)role spinning:(BOOL)spinning
5773 [
self removeDemoShips];
5775 [PLAYER setShowDemoShips: YES];
5776 Quaternion q2 = { (GLfloat)
M_SQRT1_2, (GLfloat)
M_SQRT1_2, (GLfloat)0.0, (GLfloat)0.0 };
5778 ShipEntity *ship = [
self newShipWithRole:role];
5788 [UNIVERSE addEntity:ship];
5798 [ship
setStatus:STATUS_COCKPIT_DISPLAY];
5805 return [ship autorelease];
5809- (BOOL) isVectorClearFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5817 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5819 double nearest = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z) - dist;
5825 int ent_count = n_entities;
5826 Entity* my_entities[ent_count];
5827 for (i = 0; i < ent_count; i++)
5828 my_entities[i] = [sortedEntities[i] retain];
5830 if (v1.x || v1.y || v1.z)
5831 f1 = HPvector_normal(v1);
5833 f1 = make_HPvector(0, 0, 1);
5835 for (i = 0; i < ent_count ; i++)
5837 Entity *e2 = my_entities[i];
5838 if ((e2 != e1)&&([e2 canCollide]))
5841 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5843 double d_forward = HPdot_product(epos,f1);
5845 if ((d_forward > 0)&&(d_forward < nearest))
5849 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5852 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5854 double dist2 = p0.x * p0.x + p0.
y * p0.
y + p0.z * p0.z;
5857 for (i = 0; i < ent_count; i++)
5858 [my_entities[i] release];
5864 for (i = 0; i < ent_count; i++)
5865 [my_entities[i] release];
5870- (
Entity*) hazardOnRouteFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5878 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5880 double nearest = HPmagnitude(v1) - dist;
5887 int ent_count = n_entities;
5888 Entity* my_entities[ent_count];
5889 for (i = 0; i < ent_count; i++)
5890 my_entities[i] = [sortedEntities[i] retain];
5892 if (v1.x || v1.y || v1.z)
5893 f1 = HPvector_normal(v1);
5895 f1 = make_HPvector(0, 0, 1);
5897 for (i = 0; (i < ent_count) && (!result) ; i++)
5899 Entity *e2 = my_entities[i];
5900 if ((e2 != e1)&&([e2 canCollide]))
5903 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5905 double d_forward = HPdot_product(epos,f1);
5907 if ((d_forward > 0)&&(d_forward < nearest))
5911 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5914 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5916 double dist2 = HPmagnitude2(p0);
5922 for (i = 0; i < ent_count; i++)
5923 [my_entities[i] release];
5928- (HPVector) getSafeVectorFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5939 HPVector result = p2;
5941 int ent_count = n_entities;
5942 Entity* my_entities[ent_count];
5943 for (i = 0; i < ent_count; i++)
5944 my_entities[i] = [sortedEntities[i] retain];
5947 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5949 double nearest = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z) - dist;
5951 if (v1.x || v1.y || v1.z)
5952 f1 = HPvector_normal(v1);
5954 f1 = make_HPvector(0, 0, 1);
5956 for (i = 0; i < ent_count; i++)
5958 Entity *e2 = my_entities[i];
5959 if ((e2 != e1)&&([e2 canCollide]))
5962 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5963 double d_forward = HPdot_product(epos,f1);
5964 if ((d_forward > 0)&&(d_forward < nearest))
5969 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5973 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5976 double dist2 = p0.x * p0.x + p0.
y * p0.
y + p0.z * p0.z;
5981 nearest = d_forward;
5987 result.x += ((
int)(
Ranrot() % 1024) - 512)/512.0;
5988 result.y += ((
int)(
Ranrot() % 1024) - 512)/512.0;
5989 result.z += ((
int)(
Ranrot() % 1024) - 512)/512.0;
5992 HPVector nearest_point = p1;
5993 nearest_point.x += d_forward * f1.
x; nearest_point.y += d_forward * f1.
y; nearest_point.z += d_forward * f1.z;
5996 HPVector outward = nearest_point;
5997 outward.x -= result.
x; outward.y -= result.
y; outward.z -= result.z;
5998 if (outward.x||outward.y||outward.z)
5999 outward = HPvector_normal(outward);
6004 HPVector backward = p1;
6005 backward.x -= result.
x; backward.y -= result.
y; backward.z -= result.z;
6006 if (backward.x||backward.y||backward.z)
6007 backward = HPvector_normal(backward);
6012 HPVector dd = result;
6013 dd.x -= p1.
x; dd.y -= p1.
y; dd.z -= p1.z;
6014 double current_distance = HPmagnitude(dd);
6017 if (current_distance < cr * 1.25)
6018 current_distance = cr * 1.25;
6019 if (current_distance > cr * 5.0)
6020 current_distance = cr * 5.0;
6024 result.x += 0.25 * (outward.
x * current_distance) + 0.75 * (backward.
x * current_distance);
6025 result.y += 0.25 * (outward.
y * current_distance) + 0.75 * (backward.
y * current_distance);
6026 result.z += 0.25 * (outward.z * current_distance) + 0.75 * (backward.z * current_distance);
6032 for (i = 0; i < ent_count; i++)
6033 [my_entities[i] release];
6038- (
ShipEntity*) addWreckageFrom:(
ShipEntity *)ship withRole:(NSString *)wreckRole at:(HPVector)rpos scale:(GLfloat)scale lifetime:(GLfloat)lifetime
6040 ShipEntity* wreck = [UNIVERSE newShipWithRole:wreckRole];
6044 GLfloat expected_mass = 0.1f * [ship
mass] * (0.75 + 0.5 *
randf());
6045 GLfloat wreck_mass = [wreck
mass];
6046 GLfloat scale_factor = powf(expected_mass / wreck_mass, 0.33333333f) * scale;
6062 [UNIVERSE addEntity:wreck];
6072- (void) addLaserHitEffectsAt:(HPVector)pos against:(
ShipEntity *)target damage:(
float)damage color:(
OOColor *)color
6075 if ([target showDamage] && [target energy] < [target maxEnergy]/2)
6077 NSString *key = (
randf() < 0.5) ?
@"oolite-hull-spark" :
@"oolite-hull-spark-b";
6078 NSDictionary *settings = [UNIVERSE explosionSetting:key];
6081 [
self addEntity: burst];
6082 if ([target energy] *
randf() < damage)
6084 ShipEntity *wreck = [
self addWreckageFrom:target withRole:@"oolite-wreckage-chunk" at:pos scale:0.05 lifetime:(125.0+(randf()*200.0))];
6087 Vector direction = HPVectorToVector(HPvector_normal(HPvector_subtract(pos,[target position])));
6088 [wreck
setVelocity:vector_add([wreck
velocity],vector_multiply_scalar(direction,10+20*randf()))];
6099- (
ShipEntity *) firstShipHitByLaserFromShip:(
ShipEntity *)srcEntity inDirection:(
OOWeaponFacing)direction offset:(Vector)offset gettingRangeFound:(GLfloat *)range_ptr
6101 if (srcEntity ==
nil)
return nil;
6105 HPVector p0 = [srcEntity
position];
6113 HPVector midfrontplane = make_HPvector(0.5 * (bbox.max.x + bbox.min.x), 0.5 * (bbox.max.y + bbox.min.y), bbox.max.z);
6116 if ([parent isPlayer]) q1.w = -q1.w;
6121 int ent_count = n_entities;
6125 for (i = 0; i < ent_count; i++)
6127 Entity* ent = sortedEntities[i];
6128 if (ent != srcEntity && ent != parent && [ent isShip] && [ent canCollide])
6159 HPVector p1 = HPvector_add(p0, vectorToHPVector(vector_multiply_scalar(f1, nearest)));
6161 for (i = 0; i < ship_count; i++)
6167 Vector rpos = HPVectorToVector(HPvector_subtract(e2->
position, p0));
6168 Vector v_off = make_vector(dot_product(rpos, r1), dot_product(rpos, u1), dot_product(rpos, f1));
6169 if (v_off.z > 0.0 && v_off.z < nearest + cr &&
6170 v_off.x < cr && v_off.x > -cr && v_off.y < cr && v_off.y > -cr &&
6171 v_off.x * v_off.x + v_off.y * v_off.y < cr * cr)
6174 GLfloat hit = [(
ShipEntity *)
e2 doesHitLine:p0 :p1 :&entHit];
6176 if (hit > 0.0 && hit < nearest)
6178 if ([entHit isSubEntity])
6180 hit_subentity = entHit;
6184 p1 = HPvector_add(p0, vectorToHPVector(vector_multiply_scalar(f1, nearest)));
6194 if (range_ptr != NULL)
6196 *range_ptr = nearest;
6200 for (i = 0; i < ship_count; i++) [my_entities[i] release];
6206- (
Entity *) firstEntityTargetedByPlayer
6211 nearest2 *= nearest2;
6213 int ent_count = n_entities;
6215 Entity *my_entities[ent_count];
6217 for (i = 0; i < ent_count; i++)
6219 if (([sortedEntities[i] isShip] && ![sortedEntities[i] isPlayer]) || [sortedEntities[i] isWormhole])
6221 my_entities[ship_count++] = [sortedEntities[i] retain];
6233 switch (viewDirection)
6241 case VIEW_STARBOARD :
6249 for (i = 0; i < ship_count; i++)
6251 Entity *e2 = my_entities[i];
6252 if ([e2 canCollide] && [e2 scanClass] != CLASS_NO_DRAW)
6254 Vector rp = HPVectorToVector(HPvector_subtract([e2 position], p1));
6256 if (dist2 < nearest2)
6259 if (df > 0.0 && df * df < nearest2)
6264 if (du * du + dr * dr < cr * cr)
6274 if (hit_entity !=
nil && [hit_entity isShip])
6277 if ([ship isJammingScanning] && ![player hasMilitaryScannerFilter])
6283 for (i = 0; i < ship_count; i++)
6285 [my_entities[i] release];
6292- (
Entity *) firstEntityTargetedByPlayerPrecisely
6298 switch (viewDirection)
6315 case VIEW_STARBOARD:
6326 return [
self firstShipHitByLaserFromShip:PLAYER inDirection:targetFacing offset:laserPortOffset gettingRangeFound:NULL];
6330- (NSArray *) entitiesWithinRange:(
double)range ofEntity:(
Entity *)entity
6332 if (entity ==
nil)
return nil;
6334 return [
self findShipsMatchingPredicate:YESPredicate
6341- (unsigned) countShipsWithRole:(NSString *)role inRange:(
double)range ofEntity:(
Entity *)entity
6343 return [
self countShipsMatchingPredicate:HasRolePredicate
6350- (unsigned) countShipsWithRole:(NSString *)role
6352 return [
self countShipsWithRole:role inRange:-1 ofEntity:nil];
6356- (unsigned) countShipsWithPrimaryRole:(NSString *)role inRange:(
double)range ofEntity:(
Entity *)entity
6358 return [
self countShipsMatchingPredicate:HasPrimaryRolePredicate
6365- (unsigned) countShipsWithScanClass:(
OOScanClass)scanClass inRange:(
double)range ofEntity:(
Entity *)entity
6367 return [
self countShipsMatchingPredicate:HasScanClassPredicate
6368 parameter:[NSNumber numberWithInt:scanClass]
6374- (unsigned) countShipsWithPrimaryRole:(NSString *)role
6376 return [
self countShipsWithPrimaryRole:role inRange:-1 ofEntity:nil];
6381 parameter:(
void *)parameter
6382 inRange:(
double)range
6385 unsigned i, found = 0;
6387 double distance, cr;
6394 for (i = 0; i < n_entities; i++)
6396 Entity *e2 = sortedEntities[i];
6397 if (e2 != e1 && predicate(e2, parameter))
6399 if (range < 0) distance = -1;
6402 cr = range + e2->collision_radius;
6403 distance = HPdistance2(e2->
position, p1) - cr * cr;
6417 parameter:(
void *)parameter
6418 inRange:(
double)range
6419 ofEntity:(
Entity *)entity
6421 if (predicate != NULL)
6426 predicate, parameter
6429 return [
self countEntitiesMatchingPredicate:ANDPredicate
6436 return [
self countEntitiesMatchingPredicate:IsShipPredicate
6446 if (range < 0)
return YES;
6448 return HPdistance2(e2->
position,p1) < cr * cr;
6455 parameter:(
void *)parameter
6456 inRange:(
double)range
6463 NSMutableArray *result =
nil;
6469 result = [NSMutableArray arrayWithCapacity:n_entities];
6474 for (i = 0; i < n_entities; i++)
6476 Entity *e2 = sortedEntities[i];
6480 predicate(e2, parameter))
6482 [result addObject:e2];
6495 parameter:(
void *)parameter
6504 for (i = 0; i < n_entities; i++)
6506 candidate = sortedEntities[i];
6507 if (predicate(candidate, parameter))
return candidate;
6517 parameter:(
void *)parameter
6518 inRange:(
double)range
6519 ofEntity:(
Entity *)entity
6521 if (predicate != NULL)
6526 predicate, parameter
6529 return [
self findEntitiesMatchingPredicate:ANDPredicate
6536 return [
self findEntitiesMatchingPredicate:IsShipPredicate
6545 parameter:(
void *)parameter
6546 inRange:(
double)range
6547 ofEntity:(
Entity *)entity
6549 if (predicate != NULL)
6554 predicate, parameter
6557 return [
self findEntitiesMatchingPredicate:ANDPredicate
6564 return [
self findEntitiesMatchingPredicate:IsVisualEffectPredicate
6573 parameter:(
void *)parameter
6574 relativeToEntity:(
Entity *)entity
6578 float rangeSq = INFINITY;
6586 for (i = 0; i < n_entities; i++)
6588 Entity *e2 = sortedEntities[i];
6589 float distanceToReferenceEntitySquared = (float)HPdistance2(p1, [e2 position]);
6592 distanceToReferenceEntitySquared < rangeSq &&
6593 predicate(e2, parameter))
6596 rangeSq = distanceToReferenceEntitySquared;
6600 return [[result retain] autorelease];
6605 parameter:(
void *)parameter
6606 relativeToEntity:(
Entity *)entity
6608 if (predicate != NULL)
6613 predicate, parameter
6616 return [
self nearestEntityMatchingPredicate:ANDPredicate
6618 relativeToEntity:entity];
6622 return [
self nearestEntityMatchingPredicate:IsShipPredicate
6624 relativeToEntity:entity];
6631 return universal_time;
6641- (void) findCollisionsAndShadows
6645 [universeRegion clearEntityList];
6647 for (i = 0; i < n_entities; i++)
6649 [universeRegion checkEntity:sortedEntities[i]];
6652 if (![[
self gameController] isGamePaused])
6654 [universeRegion findCollisions];
6658 [universeRegion findShadowedEntities];
6662- (NSString*) collisionDescription
6664 if (universeRegion !=
nil)
return [universeRegion collisionDescription];
6669- (void) dumpCollisions
6671 dumpCollisionInfo = YES;
6677 return viewDirection;
6681- (void) setViewDirection:(
OOViewID) vd
6684 BOOL guiSelected = NO;
6686 if ((viewDirection == vd) && (vd != VIEW_CUSTOM) && (!displayGUI))
6692 ms =
DESC(
@"forward-view-string");
6696 ms =
DESC(
@"aft-view-string");
6700 ms =
DESC(
@"port-view-string");
6703 case VIEW_STARBOARD:
6704 ms =
DESC(
@"starboard-view-string");
6708 ms = [PLAYER customViewDescription];
6711 case VIEW_GUI_DISPLAY:
6712 [
self setDisplayText:YES];
6713 [
self setMainLightPosition:(Vector){ DEMO_LIGHT_POSITION }];
6724 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
6729 [[
self gameController] setMouseInteractionModeForFlight];
6732 if (viewDirection != vd || viewDirection == VIEW_CUSTOM)
6734 #if (ALLOW_CUSTOM_VIEWS_WHILE_PAUSED)
6735 BOOL gamePaused = [[
self gameController] isGamePaused];
6737 BOOL gamePaused = NO;
6742 if (ms && !gamePaused)
6744 [
self addMessage:ms forCount:3];
6746 else if (gamePaused)
6748 [message_gui clear];
6754- (void) enterGUIViewModeWithMouseInteraction:(BOOL)mouseInteraction
6756 [
self setViewDirection:VIEW_GUI_DISPLAY];
6757 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:mouseInteraction];
6761- (NSString *) soundNameForCustomSoundKey:(NSString *)key
6763 NSString *result =
nil;
6764 NSMutableSet *seen =
nil;
6765 id object = [customSounds objectForKey:key];
6767 if ([
object isKindOfClass:[NSArray class]] && [object
count] > 0)
6769 key = [object oo_stringAtIndex:Ranrot() % [object count]];
6780 seen = [NSMutableSet set];
6782 if (
object ==
nil || ([result hasPrefix:
@"["] && [result hasSuffix:
@"]"]))
6786 [seen addObject:result];
6787 object = [customSounds objectForKey:result];
6788 if( [
object isKindOfClass:[NSArray class]] && [object
count] > 0)
6790 result = [object oo_stringAtIndex:Ranrot() % [object count]];
6791 if ([key hasPrefix:
@"["] && [key hasSuffix:
@"]"]) key=result;
6795 if ([
object isKindOfClass:[NSString class]])
6800 if (result ==
nil || ![result hasPrefix:
@"["] || ![result hasSuffix:
@"]"]) break;
6801 if ([seen containsObject:result])
6803 OOLogERR(
@"sound.customSounds.recursion",
@"recursion in customsounds.plist for '%@' (at '%@'), no sound will be played.", key, result);
6810 if (result ==
nil) result =
@"__oolite-no-sound";
6814 if ([result isEqualToString:
@"__oolite-no-sound"])
6816 OOLog(
@"sound.customSounds",
@"Could not resolve sound name in customsounds.plist for '%@', no sound will be played.", key);
6823- (NSDictionary *) screenTextureDescriptorForKey:(NSString *)key
6825 id value = [screenBackgrounds objectForKey:key];
6826 while ([value isKindOfClass:[NSArray class]]) value = [value objectAtIndex:
Ranrot() % [value
count]];
6828 if ([value isKindOfClass:[NSString class]]) value = [NSDictionary dictionaryWithObject:value forKey:
@"name"];
6829 else if (![value isKindOfClass:[NSDictionary class]]) value =
nil;
6832 if (![[
self gui] preloadGUITexture:value]) value =
nil;
6838- (void) setScreenTextureDescriptorForKey:(NSString *)key descriptor:(NSDictionary *)desc
6840 NSMutableDictionary *sbCopy = [screenBackgrounds mutableCopy];
6843 [sbCopy removeObjectForKey:key];
6847 [sbCopy setObject:desc forKey:key];
6849 [screenBackgrounds release];
6850 screenBackgrounds = [sbCopy copy];
6855- (void) clearPreviousMessage
6857 if (currentMessage) [currentMessage release];
6858 currentMessage =
nil;
6862- (void) setMessageGuiBackgroundColor:(
OOColor *)some_color
6864 [message_gui setBackgroundColor:some_color];
6868- (void) displayMessage:(NSString *) text forCount:(
OOTimeDelta)count
6870 if (![currentMessage isEqual:text] || universal_time >= messageRepeatTime)
6872 if (currentMessage) [currentMessage release];
6873 currentMessage = [text retain];
6874 messageRepeatTime=universal_time + 6.0;
6875 [
self showGUIMessage:text withScroll:YES andColor:[message_gui textColor] overDuration:count];
6880- (void) displayCountdownMessage:(NSString *) text forCount:(
OOTimeDelta)count
6882 if (![currentMessage isEqual:text] && universal_time >= countdown_messageRepeatTime)
6884 if (currentMessage) [currentMessage release];
6885 currentMessage = [text retain];
6886 countdown_messageRepeatTime=universal_time +
count;
6887 [
self showGUIMessage:text withScroll:NO andColor:[message_gui textColor] overDuration:count];
6892- (void) addDelayedMessage:(NSString *)text forCount:(
OOTimeDelta)count afterDelay:(
double)delay
6894 NSMutableDictionary *msgDict = [NSMutableDictionary dictionaryWithCapacity:2];
6895 [msgDict setObject:text forKey:@"message"];
6896 [msgDict setObject:[NSNumber numberWithDouble:count] forKey:@"duration"];
6897 [
self performSelector:@selector(addDelayedMessage:) withObject:msgDict afterDelay:delay];
6901- (void) addDelayedMessage:(NSDictionary *) textdict
6903 NSString *msg =
nil;
6906 msg = [textdict oo_stringForKey:@"message"];
6907 if (msg ==
nil)
return;
6908 msg_duration = [textdict oo_nonNegativeDoubleForKey:@"duration" defaultValue:3.0];
6910 [
self addMessage:msg forCount:msg_duration];
6914- (void) addMessage:(NSString *)text forCount:(
OOTimeDelta)count
6916 [
self addMessage:text forCount:count forceDisplay:NO];
6920- (void) speakWithSubstitutions:(NSString *)text
6922#if OOLITE_SPEECH_SYNTH
6928 NSString *systemSaid =
nil;
6929 NSString *h_systemSaid =
nil;
6931 NSString *systemName = [
self getSystemName:systemID];
6933 systemSaid = systemName;
6935 NSString *h_systemName = [
self getSystemName:[player
targetSystemID]];
6936 h_systemSaid = h_systemName;
6938 NSString *spokenText = text;
6939 if (speechArray !=
nil)
6941 NSEnumerator *speechEnumerator =
nil;
6942 NSArray *thePair =
nil;
6944 for (speechEnumerator = [speechArray objectEnumerator]; (thePair = [speechEnumerator nextObject]); )
6946 NSString *original_phrase = [thePair oo_stringAtIndex:0];
6948 NSUInteger replacementIndex;
6950 replacementIndex = 1;
6952 replacementIndex = [thePair count] > 2 ? 2 : 1;
6955 NSString *replacement_phrase = [thePair oo_stringAtIndex:replacementIndex];
6956 if (![replacement_phrase isEqualToString:
@"_"])
6958 spokenText = [spokenText stringByReplacingOccurrencesOfString:original_phrase withString:replacement_phrase];
6961 spokenText = [spokenText stringByReplacingOccurrencesOfString:systemName withString:systemSaid];
6962 spokenText = [spokenText stringByReplacingOccurrencesOfString:h_systemName withString:h_systemSaid];
6964 [
self stopSpeaking];
6965 [
self startSpeakingString:spokenText];
6971- (void) addMessage:(NSString *) text forCount:(
OOTimeDelta) count forceDisplay:(BOOL) forceDisplay
6973 if (![currentMessage isEqual:text] || forceDisplay || universal_time >= messageRepeatTime)
6977 [
self speakWithSubstitutions:text];
6980 [
self showGUIMessage:text withScroll:YES andColor:[message_gui textColor] overDuration:count];
6982 [PLAYER doScriptEvent:OOJSID("consoleMessageReceived") withArgument:text];
6984 [currentMessage release];
6985 currentMessage = [text retain];
6986 messageRepeatTime=universal_time + 6.0;
6991- (void) addCommsMessage:(NSString *)text forCount:(
OOTimeDelta)count
6993 [
self addCommsMessage:text forCount:count andShowComms:_autoCommLog logOnly:NO];
6997- (void) addCommsMessage:(NSString *)text forCount:(
OOTimeDelta)count andShowComms:(BOOL)showComms logOnly:(BOOL)logOnly
6999 if ([
PLAYER showDemoShips])
return;
7001 NSString *expandedMessage =
OOExpand(text);
7003 if (![currentMessage isEqualToString:expandedMessage] || universal_time >= messageRepeatTime)
7012 NSString *format =
OOExpandKey(
@"speech-synthesis-incoming-message-@");
7013 [
self speakWithSubstitutions:[NSString stringWithFormat:format, expandedMessage]];
7016 [
self showGUIMessage:expandedMessage withScroll:YES andColor:[message_gui textCommsColor] overDuration:count];
7018 [currentMessage release];
7019 currentMessage = [expandedMessage retain];
7020 messageRepeatTime=universal_time + 6.0;
7023 [comm_log_gui printLongText:expandedMessage align:GUI_ALIGN_LEFT color:nil fadeTime:0.0 key:nil addToArray:[player
commLog]];
7025 if (showComms) [
self showCommsLog:6.0];
7032 [comm_log_gui setAlpha:1.0];
7033 if (![
self permanentCommLog]) [comm_log_gui fadeOutFromTime:[
self getTime] overDuration:how_long];
7037- (void) showGUIMessage:(NSString *)text withScroll:(BOOL)scroll andColor:(
OOColor *)selectedColor overDuration:(
OOTimeDelta)how_long
7041 [message_gui printLongText:text align:GUI_ALIGN_CENTER color:selectedColor fadeTime:how_long key:nil addToArray:nil];
7045 [message_gui printLineNoScroll:text align:GUI_ALIGN_CENTER color:selectedColor fadeTime:how_long key:nil addToArray:nil];
7047 [message_gui setAlpha:1.0f];
7051- (void) repopulateSystem
7058 [PLAYER doWorldScriptEvent:OOJSIDFromString(system_repopulator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
7066 volatile OOTimeDelta delta_t = inDeltaT * [
self timeAccelerationFactor];
7067 NSUInteger sessionID = _sessionID;
7068 OOLog(
@"universe.profile.update",
@"%@",
@"Begin update");
7071 next_repopulation -= delta_t;
7072 if (next_repopulation < 0)
7074 [
self repopulateSystem];
7077 unsigned i, ent_count = n_entities;
7078 Entity *my_entities[ent_count];
7080 [
self verifyEntitySessionIDs];
7083 for (i = 0; i < ent_count; i++)
7085 my_entities[i] = [sortedEntities[i] retain];
7088 NSString *
volatile update_stage =
@"initialisation";
7090 id volatile update_stage_param =
nil;
7097 skyClearColor[0] = 0.0;
7098 skyClearColor[1] = 0.0;
7099 skyClearColor[2] = 0.0;
7100 skyClearColor[3] = 0.0;
7102 time_delta = delta_t;
7103 universal_time += delta_t;
7105 if (
EXPECT_NOT([player showDemoShips] && [player guiScreen] == GUI_SCREEN_SHIPLIBRARY))
7107 update_stage =
@"demo management";
7109 if (universal_time >= demo_stage_time)
7121 [demo_ship setPosition:[demo_ship destination]];
7123 demo_stage_time = universal_time + 300.0;
7127 [demo_ship setVelocity:vel];
7129 demo_stage_time = universal_time + 0.25;
7133 [
self removeEntity:demo_ship];
7140 demo_ship_subindex = (demo_ship_subindex + 1) % [[demo_ships objectAtIndex:demo_ship_index] count];
7141 demo_ship = [
self newShipWithName:[[
self demoShipData] oo_stringForKey:kOODemoShipKey] usePlayerProxy:NO];
7143 if (demo_ship !=
nil)
7145 [demo_ship removeEquipmentItem:@"EQ_SHIELD_BOOSTER"];
7146 [demo_ship removeEquipmentItem:@"EQ_SHIELD_ENHANCER"];
7148 [demo_ship switchAITo:@"nullAI.plist"];
7149 [demo_ship setOrientation:q2];
7150 [demo_ship setScanClass: CLASS_NO_DRAW];
7151 [demo_ship setStatus: STATUS_COCKPIT_DISPLAY];
7152 [demo_ship setDemoShip: 1.0f];
7153 [demo_ship setDemoStartTime: universal_time];
7154 if ([
self addEntity:demo_ship])
7156 [demo_ship release];
7157 [demo_ship setStatus:STATUS_COCKPIT_DISPLAY];
7159 [demo_ship setPositionX:0.0f y:0.0f z:demo_start_z];
7160 [demo_ship setDestination: make_HPvector(0.0f, 0.0f, demo_start_z * 0.01f)];
7161 [demo_ship setVelocity:kZeroVector];
7162 [demo_ship setScanClass: CLASS_NO_DRAW];
7165 [
self setLibraryTextForDemoShip];
7168 demo_start_time=universal_time;
7183 [demo_ship setPositionX:0.0f y:[demo_ship destination].y * delta z:demo_start_z + ([demo_ship destination].z - demo_start_z) * delta ];
7187 update_stage =
@"update:entity";
7188 NSMutableSet *zombies =
nil;
7189 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7190 for (i = 0; i < ent_count; i++)
7192 Entity *thing = my_entities[i];
7194 update_stage_param = thing;
7195 update_stage =
@"update:entity [%@]";
7198 if (
EXPECT_NOT([thing status] == STATUS_DEAD && ![entitiesDeadThisUpdate containsObject:thing] && ![thing isPlayer]))
7200 if (zombies ==
nil) zombies = [NSMutableSet set];
7201 [zombies addObject:thing];
7213 update_stage =
@"update:list maintenance [%@]";
7220 while (index > 0 && z_distance < sortedEntities[index - 1]->zero_distance)
7222 sortedEntities[index] = sortedEntities[index - 1];
7223 sortedEntities[index - 1] = thing;
7225 sortedEntities[index]->zero_index = index;
7233 update_stage =
@"update:think [%@]";
7239 if ((universal_time > thinkTime)||(thinkTime == 0.0))
7248 update_stage_param =
nil;
7253 update_stage =
@"shootin' zombies";
7254 NSEnumerator *zombieEnum =
nil;
7256 for (zombieEnum = [zombies objectEnumerator]; (zombie = [zombieEnum nextObject]); )
7258 OOLogERR(
@"universe.zombie",
@"Found dead entity %@ in active entity list, removing. This is an internal error, please report it.", zombie);
7259 [
self removeEntity:zombie];
7264 update_stage =
@"updating linked lists";
7265 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7266 for (i = 0; i < ent_count; i++)
7273 update_stage =
@"collision and shadow detection";
7274 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7275 [
self filterSortedLists];
7276 [
self findCollisionsAndShadows];
7280 if (doLinkedListMaintenanceThisUpdate)
7283 doLinkedListMaintenanceThisUpdate = NO;
7286 @catch (NSException *exception)
7288 if ([[exception name] hasPrefix:
@"Oolite"])
7290 [
self handleOoliteException:exception];
7295 if (update_stage_param !=
nil) update_stage = [NSString stringWithFormat:update_stage, update_stage_param];
7297 OOLog(
kOOLogException,
@"***** Exception during [%@] in [Universe update:] : %@ : %@ *****", update_stage, [exception name], [exception reason]);
7303 update_stage =
@"clean up";
7304 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7305 for (i = 0; i < ent_count; i++)
7307 [my_entities[i] release];
7317 update_stage =
@"JS Garbage Collection";
7318 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7321 uint32 gcbytes1 = JS_GetGCParameter(JS_GetRuntime(context),JSGC_BYTES);
7327 uint32 gcbytes2 = JS_GetGCParameter(JS_GetRuntime(context),JSGC_BYTES);
7329 if (gcbytes2 < gcbytes1)
7331 OOLog(
@"universe.profile.jsgc",
@"Unplanned JS Garbage Collection from %d to %d",gcbytes1,gcbytes2);
7340 if ([
PLAYER status] == STATUS_DEAD) [PLAYER update:delta_t];
7343 [entitiesDeadThisUpdate autorelease];
7344 entitiesDeadThisUpdate =
nil;
7345 entitiesDeadThisUpdate = [[NSMutableSet alloc] initWithCapacity:n_entities];
7348 [
self prunePreloadingPlanetMaterials];
7351 OOLog(
@"universe.profile.update",
@"%@",
@"Update complete");
7356- (double) timeAccelerationFactor
7358 return timeAccelerationFactor;
7362- (void) setTimeAccelerationFactor:(
double)newTimeAccelerationFactor
7368 timeAccelerationFactor = newTimeAccelerationFactor;
7371- (double) timeAccelerationFactor
7377- (void) setTimeAccelerationFactor:(
double)newTimeAccelerationFactor
7383- (void) filterSortedLists
7393 Entity *e0, *next, *prev;
7394 OOHPScalar start, finish, next_start, next_finish, prev_start, prev_finish;
7417 start = e0->
position.z - 2.0f * e0->collision_radius;
7418 finish = start + 4.0f * e0->collision_radius;
7424 next_start = next->
position.z - 2.0f * next->collision_radius;
7425 if (next_start < finish)
7428 while ((next)&&(next_start < finish))
7431 next_finish = next_start + 4.0f * next->collision_radius;
7432 if (next_finish > finish)
7433 finish = next_finish;
7439 next_start = next->
position.z - 2.0f * next->collision_radius;
7461 start = e0->
position.z + 2.0f * e0->collision_radius;
7462 finish = start - 4.0f * e0->collision_radius;
7468 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7469 if (prev_start > finish)
7472 while ((prev)&&(prev_start > finish))
7475 prev_finish = prev_start - 4.0f * prev->collision_radius;
7476 if (prev_finish < finish)
7477 finish = prev_finish;
7483 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7507 start = e0->
position.y - 2.0f * e0->collision_radius;
7508 finish = start + 4.0f * e0->collision_radius;
7515 next_start = next->
position.y - 2.0f * next->collision_radius;
7516 if (next_start < finish)
7519 while ((next)&&(next_start < finish))
7522 next_finish = next_start + 4.0f * next->collision_radius;
7523 if (next_finish > finish)
7524 finish = next_finish;
7530 next_start = next->
position.y - 2.0f * next->collision_radius;
7552 start = e0->
position.y + 2.0f * e0->collision_radius;
7553 finish = start - 4.0f * e0->collision_radius;
7559 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7560 if (prev_start > finish)
7563 while ((prev)&&(prev_start > finish))
7566 prev_finish = prev_start - 4.0f * prev->collision_radius;
7567 if (prev_finish < finish)
7568 finish = prev_finish;
7574 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7598 start = e0->
position.x - 2.0f * e0->collision_radius;
7599 finish = start + 4.0f * e0->collision_radius;
7605 next_start = next->
position.x - 2.0f * next->collision_radius;
7606 if (next_start < finish)
7609 while ((next)&&(next_start < finish))
7612 next_finish = next_start + 4.0f * next->collision_radius;
7613 if (next_finish > finish)
7614 finish = next_finish;
7620 next_start = next->
position.x - 2.0f * next->collision_radius;
7642 start = e0->
position.x + 2.0f * e0->collision_radius;
7643 finish = start - 4.0f * e0->collision_radius;
7649 prev_start = prev->
position.x + 2.0f * prev->collision_radius;
7650 if (prev_start > finish)
7653 while ((prev)&&(prev_start > finish))
7656 prev_finish = prev_start - 4.0f * prev->collision_radius;
7657 if (prev_finish < finish)
7658 finish = prev_finish;
7664 prev_start = prev->
position.x + 2.0f * prev->collision_radius;
7688 start = e0->
position.y - 2.0f * e0->collision_radius;
7689 finish = start + 4.0f * e0->collision_radius;
7695 next_start = next->
position.y - 2.0f * next->collision_radius;
7696 if (next_start < finish)
7699 while ((next)&&(next_start < finish))
7702 next_finish = next_start + 4.0f * next->collision_radius;
7703 if (next_finish > finish)
7704 finish = next_finish;
7710 next_start = next->
position.y - 2.0f * next->collision_radius;
7731 start = e0->
position.y + 2.0f * e0->collision_radius;
7732 finish = start - 4.0f * e0->collision_radius;
7738 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7739 if (prev_start > finish)
7742 while ((prev)&&(prev_start > finish))
7745 prev_finish = prev_start - 4.0f * prev->collision_radius;
7746 if (prev_finish < finish)
7747 finish = prev_finish;
7753 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7777 start = e0->
position.z - 2.0f * e0->collision_radius;
7778 finish = start + 4.0f * e0->collision_radius;
7784 next_start = next->
position.z - 2.0f * next->collision_radius;
7785 if (next_start < finish)
7788 while ((next)&&(next_start < finish))
7793 next_finish = next_start + 4.0f * next->collision_radius;
7794 if (next_finish > finish)
7795 finish = next_finish;
7801 next_start = next->
position.z - 2.0f * next->collision_radius;
7823 start = e0->
position.z + 2.0f * e0->collision_radius;
7824 finish = start - 4.0f * e0->collision_radius;
7830 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7831 if (prev_start > finish)
7834 while ((prev)&&(prev_start > finish))
7859 OOLog(
@"general.error.inconsistentState",
@"Unexpected state in collision chain builder prev=%@, prev->c=%@, e0=%@, e0->c=%@",prev,prev->
collision_chain,e0,e0->
collision_chain);
7864 prev_finish = prev_start - 4.0f * prev->collision_radius;
7865 if (prev_finish < finish)
7866 finish = prev_finish;
7872 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7898 [
self setGalaxyTo:g andReinit:NO];
7902- (void) setGalaxyTo:(
OOGalaxyID) g andReinit:(BOOL) forced
7905 NSAutoreleasePool *pool =
nil;
7907 if (galaxyID != g || forced) {
7911 pool = [[NSAutoreleasePool alloc] init];
7913 for (i = 0; i < 256; i++)
7915 if (system_names[i])
7917 [system_names[i] release];
7919 system_names[i] = [[systemManager getProperty:@"name" forSystem:i inGalaxy:g] retain];
7929 NSDictionary *systemData;
7932 NSString *scriptName;
7939 systemData = [
self generateSystemData:targetSystemID];
7940 economy = [systemData oo_unsignedCharForKey:KEY_ECONOMY];
7941 scriptName = [systemData oo_stringForKey:@"market_script" defaultValue:nil];
7944 commodityMarket = [[commodities generateMarketForSystemWithEconomy:economy andScript:scriptName] retain];
7954- (NSDictionary *) descriptions
7956 if (_descriptions ==
nil)
7961 stringByAppendingPathComponent:@"Config"]
7962 stringByAppendingPathComponent:@"descriptions.plist"]];
7964 [
self verifyDescriptions];
7966 return _descriptions;
7970static void VerifyDesc(NSString *key,
id desc);
7975 if ([desc rangeOfString:
@"%n"].location != NSNotFound)
7977 OOLog(
@"descriptions.verify.percentN",
@"***** FATAL: descriptions.plist entry \"%@\
" contains the dangerous control sequence %%n.", key);
7986 foreach (subDesc, desc)
7988 VerifyDesc(key, subDesc);
7993static void VerifyDesc(NSString *key,
id desc)
7995 if ([desc isKindOfClass:[NSString class]])
7997 VerifyDescString(key, desc);
7999 else if ([desc isKindOfClass:[NSArray class]])
8001 VerifyDescArray(key, desc);
8003 else if ([desc isKindOfClass:[NSNumber class]])
8009 OOLogERR(
@"descriptions.verify.badType",
@"***** FATAL: descriptions.plist entry for \"%@\
" is neither a string nor an array.", key);
8027 NSString *key =
nil;
8028 if (_descriptions ==
nil)
8030 OOLog(
@"descriptions.verify",
@"%@",
@"***** FATAL: Tried to verify descriptions, but descriptions was nil - unable to load any descriptions.plist file.");
8035 VerifyDesc(key, [_descriptions objectForKey:key]);
8042 [_descriptions autorelease];
8044 [
self verifyDescriptions];
8048- (NSDictionary *) explosionSetting:(NSString *)explosion
8050 return [explosionSettings oo_dictionaryForKey:explosion defaultValue:nil];
8054- (NSArray *) scenarios
8062 [_scenarios autorelease];
8067- (NSDictionary *) characters
8073- (NSDictionary *) missiontext
8079- (NSString *)descriptionForKey:(NSString *)key
8081 return [
self chooseStringForKey:key inDictionary:[
self descriptions]];
8085- (NSString *)descriptionForArrayKey:(NSString *)key index:(
unsigned)index
8087 NSArray *array = [[
self descriptions] oo_arrayForKey:key];
8088 if ([array
count] <= index)
return nil;
8089 return [array objectAtIndex:index];
8093- (BOOL) descriptionBooleanForKey:(NSString *)key
8095 return [[
self descriptions] oo_boolForKey:key];
8101 return systemManager;
8107 return [NSString stringWithFormat:@"%d %d", g, s];
8113 return [NSString stringWithFormat:@"interstellar: %d %d %d", g, s1, s2];
8117- (NSDictionary *) generateSystemData:(
OOSystemID) s
8119 return [
self generateSystemData:s useCache:YES];
8124- (NSDictionary *) generateSystemData:(
OOSystemID) s useCache:(BOOL) useCache
8131 NSString *systemKey = [NSString stringWithFormat:@"%u %u",[PLAYER galaxyNumber],s];
8133 return [systemManager getPropertiesForSystemKey:systemKey];
8139- (NSDictionary *) currentSystemData
8143 if (![
self inInterstellarSpace])
8145 return [
self generateSystemData:systemID];
8149 static NSDictionary *interstellarDict =
nil;
8150 if (interstellarDict ==
nil)
8152 NSString *interstellarName =
DESC(
@"interstellar-space");
8153 NSString *notApplicable =
DESC(
@"not-applicable");
8154 NSNumber *minusOne = [NSNumber numberWithInt:-1];
8155 NSNumber *zero = [NSNumber numberWithInt:0];
8156 interstellarDict = [[NSDictionary alloc] initWithObjectsAndKeys:
8157 interstellarName, KEY_NAME,
8158 minusOne, KEY_GOVERNMENT,
8159 minusOne, KEY_ECONOMY,
8160 minusOne, KEY_TECHLEVEL,
8161 zero, KEY_POPULATION,
8162 zero, KEY_PRODUCTIVITY,
8164 notApplicable, KEY_INHABITANTS,
8165 notApplicable, KEY_DESCRIPTION,
8169 return interstellarDict;
8176- (BOOL) inInterstellarSpace
8178 return [
self sun] ==
nil;
8186- (void) setSystemDataKey:(NSString *)key value:(NSObject *)object fromManifest:(NSString *)manifest
8188 [
self setSystemDataForGalaxy:galaxyID planet:systemID key:key value:object fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
8192- (void) setSystemDataForGalaxy:(
OOGalaxyID)gnum planet:(
OOSystemID)pnum key:(NSString *)key value:(
id)object fromManifest:(NSString *)manifest forLayer:(
OOSystemLayer)layer
8194 static BOOL sysdataLocked = NO;
8197 OOLogERR(
@"script.error",
@"%@",
@"System properties cannot be set during 'systemInformationChanged' events to avoid infinite loops.");
8201 BOOL sameGalaxy = (gnum == [PLAYER currentGalaxyID]);
8202 BOOL sameSystem = (sameGalaxy && pnum == [
self currentSystemID]);
8205 if ([key isEqualToString:
KEY_RADIUS] && sameGalaxy && sameSystem)
8207 OOLogERR(
@"script.error",
@"System property '%@' cannot be set while in the system.",key);
8211 if ([key isEqualToString:
@"coordinates"])
8213 OOLogERR(
@"script.error",
@"System property '%@' cannot be set.",key);
8218 NSString *overrideKey = [NSString stringWithFormat:@"%u %u", gnum, pnum];
8219 NSDictionary *sysInfo =
nil;
8222 [gui refreshStarChart];
8224 if (
object !=
nil) {
8226 if ([key isEqualToString:
KEY_NAME])
8228 object=(id)[[(NSString *)
object lowercaseString] capitalizedString];
8231 if (system_names[pnum]) [system_names[pnum] release];
8232 system_names[pnum] = [(NSString *)object retain];
8235 else if ([key isEqualToString:
@"sun_radius"])
8237 if ([
object doubleValue] < 1000.0 || [
object doubleValue] > 10000000.0 )
8239 object = ([object doubleValue] < 1000.0 ? (id)
@"1000.0" : (id)
@"10000000.0");
8242 else if ([key hasPrefix:
@"corona_"])
8244 object = (id)[NSString stringWithFormat:
@"%f",OOClamp_0_1_f([object floatValue])];
8248 [systemManager setProperty:key forSystemKey:overrideKey andLayer:layer toValue:object fromManifest:manifest];
8254 sysInfo = [systemManager getPropertiesForCurrentSystem];
8264 [[
self station] setEquivalentTechLevel:[object intValue]];
8265 [[
self station] setLocalShipyard:[
self shipsForSaleForSystem:systemID
8266 withTL:[object intValue] atTime:[PLAYER clockTime]]];
8269 else if ([key isEqualToString:
@"sun_color"] || [key isEqualToString:
@"star_count_multiplier"] ||
8270 [key isEqualToString:
@"nebula_count_multiplier"] || [key hasPrefix:
@"sky_"])
8275 for (i = n_entities - 1; i > 0; i--)
8276 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[SkyEntity class]]))
8277 the_sky = (
SkyEntity*)sortedEntities[i];
8283 if ([key isEqualToString:
@"sun_color"])
8292 for (i = n_entities - 1; i > 0; i--)
8293 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[DustEntity class]]))
8294 [(
DustEntity*)sortedEntities[i] setDustColor:[color blendedColorWithFraction:0.5 ofColor:[OOColor whiteColor]]];
8298 else if (the_sun !=
nil && ([key hasPrefix:
@"sun_"] || [key hasPrefix:
@"corona_"]))
8302 else if ([key isEqualToString:
@"texture"])
8304 [[
self planet] setUpPlanetFromTexture:(NSString *)object];
8306 else if ([key isEqualToString:
@"texture_hsb_color"])
8308 [[
self planet] setUpPlanetFromTexture: [[
self planet] textureFileName]];
8310 else if ([key isEqualToString:
@"air_color"])
8314 else if ([key isEqualToString:
@"illumination_color"])
8318 else if ([key isEqualToString:
@"air_color_mix_ratio"])
8320 [[
self planet] setAirColorMixRatio:[sysInfo oo_floatForKey:key]];
8324 sysdataLocked = YES;
8325 [PLAYER doScriptEvent:OOJSID("systemInformationChanged") withArguments:[NSArray arrayWithObjects:[NSNumber numberWithInt:gnum],[NSNumber numberWithInt:pnum],key,object,nil]];
8333 NSString *systemKey = [
self keyForPlanetOverridesForSystem:pnum inGalaxy:gnum];
8334 return [systemManager getPropertiesForSystemKey:systemKey];
8340 return [[
self generateSystemDataForGalaxy:gnum planet:pnum] allKeys];
8347 return [systemManager getProperty:key forSystem:pnum inGalaxy:gnum];
8353 return [
self getSystemName:sys forGalaxy:galaxyID];
8359 return [systemManager getProperty:@"name" forSystem:sys inGalaxy:gnum];
8365 return [[systemManager getProperty:@"government" forSystem:sys inGalaxy:galaxyID] unsignedCharValue];
8369- (NSString *) getSystemInhabitants:(
OOSystemID) sys
8371 return [
self getSystemInhabitants:sys plural:YES];
8375- (NSString *) getSystemInhabitants:(
OOSystemID) sys plural:(BOOL)plural
8377 NSString *ret =
nil;
8380 ret = [systemManager getProperty:KEY_INHABITANT forSystem:sys inGalaxy:galaxyID];
8388 return [systemManager getProperty:KEY_INHABITANTS forSystem:sys inGalaxy:galaxyID];
8393- (NSPoint) coordinatesForSystem:(
OOSystemID)s
8395 return [systemManager getCoordinatesForSystem:s inGalaxy:galaxyID];
8399- (
OOSystemID) findSystemFromName:(NSString *) sysName
8401 if (sysName ==
nil)
return -1;
8403 NSString *system_name =
nil;
8404 NSString *match = [sysName lowercaseString];
8406 for (i = 0; i < 256; i++)
8408 system_name = [system_names[i] lowercaseString];
8409 if ([system_name isEqualToString:match])
8420 OOLog(
@"deprecated.function",
@"%@",
@"findSystemAtCoords");
8421 return [
self findSystemNumberAtCoords:coords withGalaxy:g includingHidden:YES];
8425- (NSMutableArray *) nearbyDestinationsWithinRange:(
double)range
8427 NSMutableArray *result = [NSMutableArray arrayWithCapacity:16];
8430 NSPoint here = [PLAYER galaxy_coordinates];
8432 for (
unsigned short i = 0; i < 256; i++)
8434 NSPoint there = [
self coordinatesForSystem:i];
8436 if (dist <= range && (i != systemID || [
self inInterstellarSpace]))
8438 [result addObject: [NSDictionary dictionaryWithObjectsAndKeys:
8439 [NSNumber numberWithDouble:dist], @"distance",
8440 [NSNumber numberWithInt:i], @"sysID",
8441 [[
self generateSystemData:i] oo_stringForKey:@"sun_gone_nova" defaultValue:@"0"], @"nova",
8455 double min_dist = 10000.0;
8458 BOOL connected[256];
8459 for (i = 0; i < 256; i++)
8462 for (n = 0; n < 3; n++)
8464 for (i = 0; i < 256; i++)
8466 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8467 for (j = 0; j < 256; j++)
8469 NSPoint jpos = [systemManager getCoordinatesForSystem:j inGalaxy:g];
8473 connected[j] |= connected[i];
8474 connected[i] |= connected[j];
8480 for (i = 0; i < 256; i++)
8482 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8484 if ((connected[i])&&(distance < min_dist)&&(distance != 0.0))
8486 min_dist = distance;
8502 double min_dist = 10000.0;
8505 BOOL connected[256];
8506 for (i = 0; i < 256; i++)
8509 for (n = 0; n < 3; n++)
8511 for (i = 0; i < 256; i++)
8513 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8514 for (j = 0; j < 256; j++)
8516 NSPoint jpos = [systemManager getCoordinatesForSystem:j inGalaxy:g];
8520 connected[j] |= connected[i];
8521 connected[i] |= connected[j];
8527 for (i = 0; i < 256; i++)
8529 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8531 if ((connected[i])&&(distance < min_dist))
8533 min_dist = distance;
8542- (
OOSystemID) findSystemNumberAtCoords:(NSPoint) coords withGalaxy:(
OOGalaxyID)g includingHidden:(BOOL)hidden
8551 unsigned distance, dx, dy;
8553 unsigned min_dist = 10000;
8555 for (i = 0; i < 256; i++)
8558 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:g];
8559 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8565 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8566 dx =
ABS(coords.x - ipos.x);
8567 dy =
ABS(coords.y - ipos.y);
8569 if (dx > dy) distance = (dx + dx + dy) / 2;
8570 else distance = (dx + dy + dy) / 2;
8572 if (distance < min_dist)
8574 min_dist = distance;
8578 if ((distance == min_dist)&&(coords.y > ipos.y))
8583 else if ((distance == min_dist)&&(coords.y == ipos.y)&&(i==[
PLAYER targetSystemID]))
8592- (NSPoint) findSystemCoordinatesWithPrefix:(NSString *) p_fix
8594 return [
self findSystemCoordinatesWithPrefix:p_fix exactMatch:NO];
8598- (NSPoint) findSystemCoordinatesWithPrefix:(NSString *) p_fix exactMatch:(BOOL) exactMatch
8600 NSString *system_name =
nil;
8601 NSPoint system_coords = NSMakePoint(-1.0,-1.0);
8604 for (i = 0; i < 256; i++)
8606 system_found[i] = NO;
8607 system_name = [system_names[i] lowercaseString];
8608 if ((exactMatch && [system_name isEqualToString:p_fix]) || (!exactMatch && [system_name hasPrefix:p_fix]))
8611 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxyID];
8612 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8618 system_found[i] = YES;
8621 system_coords = [systemManager getCoordinatesForSystem:i inGalaxy:galaxyID];
8626 return system_coords;
8630- (BOOL*) systemsFound
8632 return (BOOL*)system_found;
8636- (NSString*)systemNameIndex:(
OOSystemID)index
8638 return system_names[index & 255];
8655 if (start == -1 || goal == -1)
return nil;
8657#ifdef CACHE_ROUTE_FROM_SYSTEM_RESULTS
8659 static NSDictionary *c_route =
nil;
8663 if (c_route !=
nil && c_start == start && c_goal == goal && c_optimizeBy == optimizeBy)
8672 if (start > 255 || goal > 255)
return nil;
8674 NSArray *neighbours[256];
8675 BOOL concealed[256];
8676 for (i = 0; i < 256; i++)
8678 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxyID];
8679 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8682 neighbours[i] = [NSArray array];
8687 neighbours[i] = [
self neighboursToSystem:i];
8694 double maxCost = optimizeBy ==
OPTIMIZED_BY_TIME ? 256 * (7 * 7) : 256 * (7 * 256 + 7);
8696 NSMutableArray *curr = [NSMutableArray arrayWithCapacity:256];
8699 NSMutableArray *next = [NSMutableArray arrayWithCapacity:256];
8700 while ([curr
count] != 0)
8702 for (i = 0; i < [curr count]; i++) {
8704 NSArray *ns = neighbours[[elemI
location]];
8705 for (j = 0; j < [ns count]; j++)
8715 NSPoint cpos = [systemManager getCoordinatesForSystem:c inGalaxy:galaxyID];
8716 NSPoint npos = [systemManager getCoordinatesForSystem:n inGalaxy:galaxyID];
8719 double lastTime = lastDistance * lastDistance;
8721 double distance = [ce
distance] + lastDistance;
8722 double time = [ce
time] + lastTime;
8724 int jumps = [ce
jumps] + 1;
8726 if (cost < maxCost && (cheapest[n] ==
nil || [cheapest[n] cost] > cost)) {
8731 if (n == goal && cost < maxCost)
8736 [curr setArray:next];
8737 [next removeAllObjects];
8741 if (!cheapest[goal])
return nil;
8743 NSMutableArray *route = [NSMutableArray arrayWithCapacity:256];
8747 [route insertObject:[NSNumber numberWithInt:[e
location]] atIndex:0];
8748 if ([e parent] == -1)
break;
8749 e = cheapest[[e
parent]];
8752#ifdef CACHE_ROUTE_FROM_SYSTEM_RESULTS
8755 c_optimizeBy = optimizeBy;
8757 c_route = [[NSDictionary alloc] initWithObjectsAndKeys: route, @"route", [NSNumber numberWithDouble:[cheapest[goal]
distance]], @"distance", nil];
8761 return [NSDictionary dictionaryWithObjectsAndKeys:
8763 [NSNumber numberWithDouble:[cheapest[goal]
distance]], @"distance",
8764 [NSNumber numberWithDouble:[cheapest[goal]
time]], @"time",
8765 [NSNumber numberWithInt:[cheapest[goal]
jumps]], @"jumps",
8771- (NSArray *) neighboursToSystem: (
OOSystemID) s
8773 if (s == systemID && closeSystems !=
nil)
8775 return closeSystems;
8777 NSArray *neighbours = [systemManager getNeighbourIDsForSystem:s inGalaxy:galaxyID];
8781 [closeSystems release];
8782 closeSystems = [neighbours copy];
8783 return closeSystems;
8817- (void) preloadPlanetTexturesForSystem:(
OOSystemID)s
8821 [
self prunePreloadingPlanetMaterials];
8823 if ([_preloadingPlanetMaterials
count] < 3)
8825 if (_preloadingPlanetMaterials ==
nil) _preloadingPlanetMaterials = [[NSMutableArray alloc] initWithCapacity:4];
8827 OOPlanetEntity *planet = [[OOPlanetEntity alloc] initAsMainPlanetForSystem:s];
8833 if (![surface isFinishedLoading])
8835 [_preloadingPlanetMaterials addObject:surface];
8839 OOMaterial *atmo = [planet atmosphereMaterial];
8840 if (atmo !=
nil) [_preloadingPlanetMaterials addObject:atmo];
8850- (NSDictionary *) globalSettings
8852 return globalSettings;
8856- (NSArray *) equipmentData
8858 return equipmentData;
8862- (NSArray *) equipmentDataOutfitting
8864 return equipmentDataOutfitting;
8870 return commodityMarket;
8874- (NSString *) timeDescription:(
double) interval
8876 double r_time = interval;
8877 NSString* result =
@"";
8881 int days = floor(r_time / 86400);
8882 r_time -= 86400 * days;
8883 result = [NSString stringWithFormat:@"%@ %d day%@", result, days, (days > 1) ? @"s" : @""];
8887 int hours = floor(r_time / 3600);
8888 r_time -= 3600 * hours;
8889 result = [NSString stringWithFormat:@"%@ %d hour%@", result, hours, (hours > 1) ? @"s" : @""];
8893 int mins = floor(r_time / 60);
8894 r_time -= 60 * mins;
8895 result = [NSString stringWithFormat:@"%@ %d minute%@", result, mins, (mins > 1) ? @"s" : @""];
8899 int secs = floor(r_time);
8900 result = [NSString stringWithFormat:@"%@ %d second%@", result, secs, (secs > 1) ? @"s" : @""];
8902 return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
8906- (NSString *) shortTimeDescription:(
double) interval
8908 double r_time = interval;
8909 NSString* result =
@"";
8912 if (interval <= 0.0)
8913 return DESC(
@"contracts-no-time");
8917 int days = floor(r_time / 86400);
8918 r_time -= 86400 * days;
8919 result = [NSString stringWithFormat:@"%@ %d %@", result, days, DESC_PLURAL(@"contracts-day-word", days)];
8924 int hours = floor(r_time / 3600);
8925 r_time -= 3600 * hours;
8926 result = [NSString stringWithFormat:@"%@ %d %@", result, hours, DESC_PLURAL(@"contracts-hour-word", hours)];
8929 if (parts < 2 && r_time > 60)
8931 int mins = floor(r_time / 60);
8932 r_time -= 60 * mins;
8933 result = [NSString stringWithFormat:@"%@ %d %@", result, mins, DESC_PLURAL(@"contracts-minute-word", mins)];
8936 if (parts < 2 && r_time > 0)
8938 int secs = floor(r_time);
8939 result = [NSString stringWithFormat:@"%@ %d %@", result, secs, DESC_PLURAL(@"contracts-second-word", secs)];
8941 return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
8945- (void) makeSunSkimmer:(
ShipEntity *) ship andSetAI:(BOOL)setAI
8947 if (setAI) [ship
switchAITo:@"oolite-traderAI.js"];
8951 if ([ship heatInsulation] < minInsulation) [ship
setHeatInsulation:minInsulation];
8957 Random_Seed ret = [systemManager getRandomSeedForCurrentSystem];
8973- (void) loadStationMarkets:(NSArray *)marketData
8975 if (marketData ==
nil)
8980 NSArray *stations = [
self stations];
8982 NSDictionary *savedMarket =
nil;
8984 foreach (savedMarket, marketData)
8986 HPVector pos = [savedMarket oo_hpvectorForKey:@"position"];
8987 foreach (station, stations)
8990 if ([station allowsSaving] && station != [
UNIVERSE station])
8993 if (HPdistance2(pos,[station position]) < 1000000)
8995 [station setLocalMarket:[savedMarket oo_arrayForKey:@"market"]];
9005- (NSArray *) getStationMarkets
9007 NSMutableArray *markets = [[NSMutableArray alloc] init];
9008 NSArray *stations = [
self stations];
9011 NSMutableDictionary *savedMarket =
nil;
9015 foreach (station, stations)
9018 if ([station allowsSaving] && station != [
UNIVERSE station])
9020 stationMarket = [station localMarket];
9021 if (stationMarket !=
nil)
9023 savedMarket = [NSMutableDictionary dictionaryWithCapacity:2];
9025 [savedMarket setObject:ArrayFromHPVector([station position]) forKey:@"position"];
9026 [markets addObject:savedMarket];
9031 return [markets autorelease];
9040 NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionary];
9042 float tech_price_boost = (ship_seed.
a + ship_seed.b) / 256.0;
9048 for (i = 0; i < 256; i++)
9050 long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
9052 long long c_time = ship_seed.
a * 0x10000 + ship_seed.b * 0x100 + ship_seed.c;
9053 double ship_sold_time = reference_time + c_time;
9055 if (ship_sold_time < 0)
9056 ship_sold_time += 0x1000000;
9058 double days_until_sale = (ship_sold_time - current_time) / 86400.0;
9060 NSMutableArray *keysForShips = [NSMutableArray arrayWithArray:[registry
playerShipKeys]];
9062 for (si = 0; si < [keysForShips count]; si++)
9065 NSString *key = [keysForShips oo_stringAtIndex:si];
9067 NSArray *conditions = [dict oo_arrayForKey:@"conditions"];
9069 if (![player scriptTestConditions:conditions])
9071 [keysForShips removeObjectAtIndex:si--];
9073 NSString *condition_script = [dict oo_stringForKey:@"condition_script"];
9074 if (condition_script !=
nil)
9076 OOJSScript *condScript = [
self getConditionScript:condition_script];
9077 if (condScript !=
nil)
9081 JSBool allow_purchase;
9085 OK = [condScript
callMethod:OOJSID("allowOfferShip")
9090 if (OK) OK = JS_ValueToBoolean(context, result, &allow_purchase);
9094 if (OK && !allow_purchase)
9099 [keysForShips removeObjectAtIndex:si--];
9106 NSDictionary *systemInfo = [
self generateSystemData:s];
9108 if (specialTL != NSNotFound)
9111 techlevel = specialTL;
9116 techlevel = [systemInfo oo_unsignedIntForKey:KEY_TECHLEVEL];
9118 unsigned ship_index = (ship_seed.
d * 0x100 + ship_seed.e) % [keysForShips
count];
9119 NSString *ship_key = [keysForShips oo_stringAtIndex:ship_index];
9121 OOTechLevelID ship_techlevel = [ship_info oo_intForKey:KEY_TECHLEVEL];
9123 double chance = 1.0 - pow(1.0 - [ship_info oo_doubleForKey:KEY_CHANCE], MAX((
OOTechLevelID)1, techlevel - ship_techlevel));
9126 int superRand1 = ship_seed.
a * 0x10000 + ship_seed.c * 0x100 + ship_seed.e;
9127 uint32_t superRand2 = ship_seed.
b * 0x10000 + ship_seed.d * 0x100 + ship_seed.f;
9132 if ((days_until_sale > 0.0) && (days_until_sale < 30.0) && (ship_techlevel <= techlevel) && (
randf() < chance) && (shipBaseDict !=
nil))
9134 NSMutableDictionary* shipDict = [NSMutableDictionary dictionaryWithDictionary:shipBaseDict];
9135 NSMutableString* shortShipDescription = [NSMutableString stringWithCapacity:256];
9136 NSString *shipName = [shipDict oo_stringForKey:@"display_name" defaultValue:[shipDict oo_stringForKey:KEY_NAME]];
9139 NSMutableArray* extras = [NSMutableArray arrayWithArray:[[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
9140 NSString* fwdWeaponString = [[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9141 NSString* aftWeaponString = [[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON];
9143 NSMutableArray* options = [NSMutableArray arrayWithArray:[ship_info oo_arrayForKey:KEY_OPTIONAL_EQUIPMENT]];
9144 OOCargoQuantity maxCargo = [shipDict oo_unsignedIntForKey:@"max_cargo"];
9150 [shortShipDescription appendFormat:@"%@:", shipName];
9158 if (fwdWeapon && fwdWeaponString) [shipDict setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9159 if (aftWeapon && aftWeaponString) [shipDict setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
9161 int passengerBerthCount = 0;
9162 BOOL customised = NO;
9163 BOOL weaponCustomized = NO;
9165 NSString *fwdWeaponDesc =
nil;
9167 NSString *shortExtrasKey =
@"shipyard-first-extra";
9172 while ((
randf() < chance) && ([options
count]))
9175 int optionIndex =
Ranrot() % [options count];
9176 NSString *equipmentKey = [options oo_stringAtIndex:optionIndex];
9183 NSString *eqShortDesc = [item
name];
9185 if ([item techLevel] > techlevel)
9188 eqTechLevel =
MIN(eqTechLevel, 15U);
9191 if (
randf() * (eqTechLevel - techlevel) < 1.0)
9194 eqPrice *= (tech_price_boost + eqTechLevel - techlevel) * 90 / 100;
9200 if ([item incompatibleEquipment] !=
nil && extras !=
nil)
9202 NSEnumerator *keyEnum =
nil;
9204 BOOL incompatible = NO;
9206 for (keyEnum = [[item incompatibleEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9208 if ([extras containsObject:key])
9210 [options removeObject:equipmentKey];
9215 if (incompatible)
break;
9218 for (keyEnum = [[item incompatibleEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9220 if ([options containsObject:key])
9222 [options removeObject:key];
9229 if (condition_script !=
nil)
9231 OOJSScript *condScript = [
self getConditionScript:condition_script];
9232 if (condScript !=
nil)
9236 JSBool allow_addition;
9240 OK = [condScript
callMethod:OOJSID("allowAwardEquipment")
9245 if (OK) OK = JS_ValueToBoolean(JScontext, result, &allow_addition);
9249 if (OK && !allow_addition)
9260 if ([item requiresEquipment] !=
nil && extras !=
nil)
9262 NSEnumerator *keyEnum =
nil;
9266 for (keyEnum = [[item requiresEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9268 if (![extras containsObject:key])
9276 if ([item requiresAnyEquipment] !=
nil && extras !=
nil)
9278 NSEnumerator *keyEnum =
nil;
9282 for (keyEnum = [[item requiresAnyEquipment] objectEnumerator]; (key = [keyEnum nextObject]); )
9284 if ([extras containsObject:key])
9294 if ([equipmentKey isEqualTo:
@"EQ_NAVAL_ENERGY_UNIT"])
9296 if ([extras containsObject:
@"EQ_ENERGY_UNIT"])
9298 [options removeObject:equipmentKey];
9303 if ([equipmentKey hasPrefix:
@"EQ_WEAPON"])
9307 if (availableFacings &
WEAPON_FACING_FORWARD && [new_weapon weaponThreatAssessment] > [fwdWeapon weaponThreatAssessment])
9310 price -= [
self getEquipmentPriceForKey:fwdWeaponString] * 90 / 1000;
9312 fwdWeaponString = equipmentKey;
9313 fwdWeapon = new_weapon;
9314 [shipDict setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9315 weaponCustomized = YES;
9316 fwdWeaponDesc = eqShortDesc;
9321 if (availableFacings &
WEAPON_FACING_AFT && (
isWeaponNone(aftWeapon) || [new_weapon weaponThreatAssessment] > [aftWeapon weaponThreatAssessment]))
9323 price -= [
self getEquipmentPriceForKey:aftWeaponString] * 90 / 1000;
9325 aftWeaponString = equipmentKey;
9326 aftWeapon = new_weapon;
9327 [shipDict setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
9331 [options removeObject:equipmentKey];
9338 if ([equipmentKey isEqualToString:
@"EQ_PASSENGER_BERTH"])
9344 [extras addObject:equipmentKey];
9345 passengerBerthCount++;
9351 [options removeObject:equipmentKey];
9357 [extras addObject:equipmentKey];
9358 if ([item isVisible])
9360 NSString *item = eqShortDesc;
9361 [shortShipDescription appendString:OOExpandKey(shortExtrasKey, item)];
9362 shortExtrasKey =
@"shipyard-additional-extra";
9365 [options removeObject:equipmentKey];
9371 [options removeObject:equipmentKey];
9376 BOOL lowercaseIgnore = [[
self descriptions] oo_boolForKey:@"lowercase_ignore"];
9378 if (passengerBerthCount)
9380 NSString* npb = (passengerBerthCount > 1)? [NSString stringWithFormat:
@"%d ", passengerBerthCount] : (id)
@"";
9381 NSString* ppb =
DESC_PLURAL(
@"passenger-berth", passengerBerthCount);
9382 NSString* extraPassengerBerthsDescription = [NSString stringWithFormat:DESC(@"extra-@-@-(passenger-berths)"), npb, ppb];
9383 NSString *item = extraPassengerBerthsDescription;
9384 [shortShipDescription appendString:OOExpandKey(shortExtrasKey, item)];
9385 shortExtrasKey =
@"shipyard-additional-extra";
9390 [shortShipDescription appendString:OOExpandKey(@"shipyard-standard-customer-model")];
9393 if (weaponCustomized)
9395 NSString *weapon = (lowercaseIgnore ? fwdWeaponDesc : [fwdWeaponDesc lowercaseString]);
9396 [shortShipDescription appendString:OOExpandKey(@"shipyard-forward-weapon-upgraded", weapon)];
9398 if (price > base_price)
9400 price = base_price +
cunningFee(price - base_price, 0.05);
9403 [shortShipDescription appendString:OOExpandKey(@"shipyard-price", price)];
9405 NSString *shipID = [NSString stringWithFormat:@"%06x-%06x", superRand1, superRand2];
9409 NSDictionary *ship_info_dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
9410 shipID, SHIPYARD_KEY_ID,
9411 ship_key, SHIPYARD_KEY_SHIPDATA_KEY,
9412 shipDict, SHIPYARD_KEY_SHIP,
9413 shortShipDescription, KEY_SHORT_DESCRIPTION,
9414 [NSNumber numberWithUnsignedLongLong:price], SHIPYARD_KEY_PRICE,
9415 extras, KEY_EQUIPMENT_EXTRAS,
9416 [NSNumber numberWithUnsignedShort:personality], SHIPYARD_KEY_PERSONALITY,
9419 [resultDictionary setObject:ship_info_dictionary forKey:shipID];
9429 NSMutableArray *resultArray = [[[resultDictionary allValues] mutableCopy] autorelease];
9430 [resultArray sortUsingFunction:compareName context:NULL];
9435 while (i < [resultArray
count])
9437 if (
compareName([resultArray objectAtIndex:i - 1], [resultArray objectAtIndex:i],
nil) == NSOrderedSame )
9439 [resultArray removeObjectAtIndex: i];
9449 return [NSArray arrayWithArray:resultArray];
9455 NSDictionary *ship1 = [(NSDictionary *)dict1 oo_dictionaryForKey:SHIPYARD_KEY_SHIP];
9456 NSDictionary *ship2 = [(NSDictionary *)dict2 oo_dictionaryForKey:SHIPYARD_KEY_SHIP];
9457 NSString *name1 = [ship1 oo_stringForKey:KEY_NAME];
9458 NSString *name2 = [ship2 oo_stringForKey:KEY_NAME];
9460 NSComparisonResult result = [[name1 lowercaseString] compare:[name2 lowercaseString]];
9461 if (result != NSOrderedSame)
9470 NSNumber *price1 = [(NSDictionary *)dict1 objectForKey:SHIPYARD_KEY_PRICE];
9471 NSNumber *price2 = [(NSDictionary *)dict2 objectForKey:SHIPYARD_KEY_PRICE];
9473 return [price1 compare:price2];
9481 NSString *ship_desc = [dict oo_stringForKey:@"ship_desc"];
9485 if (shipyard_info ==
nil)
9487 OOLogERR(
@"universe.tradeInValueForCommanderDictionary.valueCalculationError",
9488 @"Shipyard dictionary entry for ship %@ required for trade in value calculation, but does not exist. Setting ship value to 0.", ship_desc);
9492 base_price = [shipyard_info oo_unsignedLongLongForKey:SHIPYARD_KEY_PRICE defaultValue:0ULL];
9495 if(base_price == 0ULL)
return base_price;
9503 unsigned ship_missiles = [dict oo_unsignedIntForKey:@"missiles"];
9504 unsigned ship_max_passengers = [dict oo_unsignedIntForKey:@"max_passengers"];
9505 NSMutableArray *ship_extra_equipment = [NSMutableArray arrayWithArray:[[dict oo_dictionaryForKey:@"extra_equipment"] allKeys]];
9507 NSDictionary *basic_info = [shipyard_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT];
9508 unsigned base_missiles = [basic_info oo_unsignedIntForKey:KEY_EQUIPMENT_MISSILES];
9509 OOCreditsQuantity base_missiles_value = base_missiles * [UNIVERSE getEquipmentPriceForKey:@"EQ_MISSILE"] / 10;
9510 NSString *base_weapon_key = [basic_info oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9511 OOCreditsQuantity base_weapons_value = [UNIVERSE getEquipmentPriceForKey:base_weapon_key] / 10;
9512 NSMutableArray *base_extra_equipment = [NSMutableArray arrayWithArray:[basic_info oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
9513 NSString *weapon_key =
nil;
9516 base_weapon_key = [basic_info oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON defaultValue:nil];
9517 if (base_weapon_key !=
nil)
9518 base_weapons_value += [
UNIVERSE getEquipmentPriceForKey:base_weapon_key] / 10;
9525 NSArray *missileRoles = [dict oo_arrayForKey:@"missile_roles"];
9526 if (missileRoles !=
nil)
9529 for (i = 0; i < ship_missiles; i++)
9531 NSString *missile_desc = [missileRoles oo_stringAtIndex:i];
9532 if (missile_desc !=
nil && ![missile_desc isEqualToString:
@"NONE"])
9534 ship_missiles_value += [
UNIVERSE getEquipmentPriceForKey:missile_desc] / 10;
9539 ship_missiles_value = ship_missiles * [UNIVERSE getEquipmentPriceForKey:@"EQ_MISSILE"] / 10;
9542 long long extra_equipment_value = ship_max_passengers * [UNIVERSE getEquipmentPriceForKey:@"EQ_PASSENGER_BERTH"]/10;
9545 extra_equipment_value += ship_missiles_value - base_missiles_value;
9548 if (ship_fwd_weapon)
9551 ship_main_weapons_value = [UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9553 if (ship_aft_weapon)
9556 if (base_weapon_key !=
nil)
9558 ship_main_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9562 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9565 if (ship_port_weapon)
9568 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9570 if (ship_starboard_weapon)
9573 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9577 extra_equipment_value += ship_other_weapons_value;
9578 extra_equipment_value += ship_main_weapons_value - base_weapons_value;
9581 NSString *eq_key =
nil;
9585 for (i = [base_extra_equipment
count]-1; i > 0;i--)
9587 eq_key = [base_extra_equipment oo_stringAtIndex:i];
9588 if ([base_extra_equipment indexOfObject:eq_key inRange:NSMakeRange(0, i-1)] != NSNotFound)
9589 [base_extra_equipment removeObjectAtIndex:i];
9593 for (i = [base_extra_equipment
count]-1; i >= 0; i--)
9595 eq_key = [base_extra_equipment oo_stringAtIndex:i];
9596 if ([ship_extra_equipment containsObject:eq_key])
9597 [ship_extra_equipment removeObject:eq_key];
9599 extra_equipment_value -= ([
UNIVERSE getEquipmentPriceForKey:eq_key] / 10);
9605 for (i = [ship_extra_equipment
count]-1; i >= 0; i--)
9607 eq_key = [ship_extra_equipment oo_stringAtIndex:i];
9609 if ([item isPortableBetweenShips]) [ship_extra_equipment removeObjectAtIndex:i];
9613 for (i = [ship_extra_equipment
count]-1; i >= 0; i--)
9614 extra_equipment_value += ([
UNIVERSE getEquipmentPriceForKey:[ship_extra_equipment oo_stringAtIndex:i]] / 10);
9617 extra_equipment_value *= extra_equipment_value < 0 ? 1.4 : 0.9;
9621 if ((
long long)scrap_value > (
long long)base_price + extra_equipment_value)
return scrap_value;
9623 return base_price + extra_equipment_value;
9627- (NSString *) brochureDescriptionWithDictionary:(NSDictionary *)dict standardEquipment:(NSArray *)extras optionalEquipment:(NSArray *)options
9629 NSMutableArray *mut_extras = [NSMutableArray arrayWithArray:extras];
9630 NSString *allOptions = [options componentsJoinedByString:@" "];
9632 NSMutableString *desc = [NSMutableString stringWithFormat:@"The %@.", [dict oo_stringForKey: KEY_NAME]];
9638 OOCargoQuantity extra_cargo = [dict oo_unsignedIntForKey:@"extra_cargo" defaultValue:15];
9639 [desc appendFormat:@" Cargo capacity %dt", max_cargo];
9640 BOOL canExpand = ([allOptions rangeOfString:@"EQ_CARGO_BAY"].location != NSNotFound);
9642 [desc appendFormat:@" (expandable to %dt at most starports)", max_cargo + extra_cargo];
9643 [desc appendString:@"."];
9647 float top_speed = [dict oo_intForKey:@"max_flight_speed"];
9648 [desc appendFormat:@" Top speed %.3fLS.", 0.001 * top_speed];
9651 if ([mut_extras
count])
9653 unsigned n_berths = 0;
9655 for (i = 0; i < [mut_extras count]; i++)
9657 NSString* item_key = [mut_extras oo_stringAtIndex:i];
9658 if ([item_key isEqual:
@"EQ_PASSENGER_BERTH"])
9661 [mut_extras removeObjectAtIndex:i--];
9667 [desc appendString:@" Includes luxury accomodation for a single passenger."];
9669 [desc appendFormat:@" Includes luxury accomodation for %d passengers.", n_berths];
9674 if ([mut_extras
count])
9676 [desc appendString:@"\nComes with"];
9678 for (i = 0; i < [mut_extras count]; i++)
9680 NSString* item_key = [mut_extras oo_stringAtIndex:i];
9681 NSString* item_desc =
nil;
9682 for (j = 0; ((j < [equipmentData count])&&(!item_desc)) ; j++)
9684 NSString *eq_type = [[equipmentData oo_arrayAtIndex:j] oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
9685 if ([eq_type isEqual:item_key])
9690 switch ([mut_extras
count] - i)
9693 [desc appendFormat:@" %@ fitted as standard.", item_desc];
9696 [desc appendFormat:@" %@ and", item_desc];
9699 [desc appendFormat:@" %@,", item_desc];
9707 if ([options
count])
9709 [desc appendString:@"\nCan additionally be outfitted with"];
9711 for (i = 0; i < [options count]; i++)
9713 NSString* item_key = [options oo_stringAtIndex:i];
9714 NSString* item_desc =
nil;
9715 for (j = 0; ((j < [equipmentData count])&&(!item_desc)) ; j++)
9717 NSString *eq_type = [[equipmentData oo_arrayAtIndex:j] oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
9718 if ([eq_type isEqual:item_key])
9723 switch ([options
count] - i)
9726 [desc appendFormat:@" %@ at suitably equipped starports.", item_desc];
9729 [desc appendFormat:@" %@ and/or", item_desc];
9732 [desc appendFormat:@" %@,", item_desc];
9743- (HPVector) getWitchspaceExitPosition
9749- (Quaternion) getWitchspaceExitRotation
9752 Quaternion q_result;
9762 quaternion_normalize(&q_result);
9768- (HPVector) getSunSkimStartPositionForShip:(
ShipEntity*) ship
9784 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9785 if (v1.x||v1.y||v1.z)
9786 v1 = HPvector_normal(v1);
9790 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9791 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9797- (HPVector) getSunSkimEndPositionForShip:(
ShipEntity*) ship
9813 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9814 if (v1.x||v1.y||v1.z)
9815 v1 = HPvector_normal(v1);
9819 if (v2.x||v2.y||v2.z)
9820 v2 = HPvector_normal(v2);
9823 HPVector v3 = HPcross_product(v1, v2);
9824 if (v3.x||v3.y||v3.z)
9825 v3 = HPvector_normal(v3);
9829 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9830 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9831 v1.x += 15000 * v3.
x; v1.y += 15000 * v3.
y; v1.z += 15000 * v3.z;
9832 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9833 if (v1.x||v1.y||v1.z)
9834 v1 = HPvector_normal(v1);
9837 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9838 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9844- (NSArray *) listBeaconsWithCode:(NSString *)code
9846 NSMutableArray *result = [NSMutableArray array];
9847 Entity <OOBeaconEntity> *beacon = [
self firstBeacon];
9849 while (beacon !=
nil)
9851 NSString *beaconCode = [beacon beaconCode];
9852 if ([beaconCode rangeOfString:code options: NSCaseInsensitiveSearch].location != NSNotFound)
9854 [result addObject:beacon];
9856 beacon = [beacon nextBeacon];
9859 return [result sortedArrayUsingSelector:@selector(compareBeaconCodeWith:)];
9863- (void) allShipsDoScriptEvent:(jsid)event andReactToAIMessage:(NSString *)message
9866 int ent_count = n_entities;
9869 for (i = 0; i < ent_count; i++)
9871 if (sortedEntities[i]->isShip)
9877 for (i = 0; i < ship_count; i++)
9881 if (message !=
nil) [[se getAI] reactToMessage:message context:
@"global message"];
9896 return comm_log_gui;
9909 [message_gui clear];
9910 [comm_log_gui clear];
9911 [comm_log_gui printLongText:DESC(@"communications-log-string")
9912 align:GUI_ALIGN_CENTER color:[
OOColor yellowColor] fadeTime:0 key:nil addToArray:nil];
9916- (void) resetCommsLogColor
9922- (void) setDisplayText:(BOOL) value
9924 displayGUI = !!value;
9934- (void) setDisplayFPS:(BOOL) value
9936 displayFPS = !!value;
9946- (void) setAutoSave:(BOOL) value
9949 [[NSUserDefaults standardUserDefaults] setBool:autoSave forKey:@"autosave"];
9959- (void) setAutoSaveNow:(BOOL) value
9961 autoSaveNow = !!value;
9971- (void) setWireframeGraphics:(BOOL) value
9973 wireframeGraphics = !!value;
9974 [[NSUserDefaults standardUserDefaults] setBool:wireframeGraphics forKey:@"wireframe-graphics"];
9978- (BOOL) wireframeGraphics
9980 return wireframeGraphics;
9984- (BOOL) reducedDetail
10005 detailLevel = value;
10012 [
self setDetailLevelDirectly:value];
10013 [[NSUserDefaults standardUserDefaults] setInteger:detailLevel forKey:@"detailLevel"];
10016 if (old != detailLevel)
10026 return detailLevel;
10036- (void) handleOoliteException:(NSException *)exception
10038 if (exception !=
nil)
10043 [player
setStatus:STATUS_HANDLING_ERROR];
10045 OOLog(
kOOLogException,
@"***** Handling Fatal : %@ : %@ *****",[exception name], [exception reason]);
10046 NSString* exception_msg = [NSString stringWithFormat:@"Exception : %@ : %@ Please take a screenshot and/or press esc or Q to quit.", [exception name], [exception reason]];
10047 [
self addMessage:exception_msg forCount:30.0];
10048 [[
self gameController] setGamePaused:YES];
10052 OOLog(
kOOLogException,
@"***** Handling Non-fatal : %@ : %@ *****",[exception name], [exception reason]);
10058- (GLfloat)airResistanceFactor
10060 return airResistanceFactor;
10064- (void) setAirResistanceFactor:(GLfloat)newFactor
10066 airResistanceFactor = OOClamp_0_1_f(newFactor);
10073- (void) startSpeakingString:(NSString *) text
10075 [speechSynthesizer startSpeakingString:[NSString stringWithFormat:@"[[volm %.3f]]%@", 0.3333333f * [
OOSound masterVolume], text]];
10079- (void) stopSpeaking
10081 if ([speechSynthesizer respondsToSelector:@selector(stopSpeakingAtBoundary:)])
10083 [speechSynthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary];
10087 [speechSynthesizer stopSpeaking];
10094 return [speechSynthesizer isSpeaking];
10099- (void) startSpeakingString:(NSString *) text
10101 NSData *utf8 = [text dataUsingEncoding:NSUTF8StringEncoding];
10105 const char *stringToSay = [text UTF8String];
10106 espeak_Synth(stringToSay, strlen(stringToSay) + 1 , 0, POS_CHARACTER, 0, espeakCHARS_UTF8 | espeakPHONEMES | espeakENDPAUSE, NULL, NULL);
10111- (void) stopSpeaking
10119 return espeak_IsPlaying();
10123- (NSString *) voiceName:(
unsigned int) index
10125 if (index >= espeak_voice_count)
10127 return [NSString stringWithCString: espeak_voices[index]->name];
10131- (
unsigned int) voiceNumber:(NSString *) name
10136 const char *
const label = [name UTF8String];
10140 unsigned int index = -1;
10141 while (espeak_voices[++index] && strcmp (espeak_voices[index]->name, label))
10143 return (index < espeak_voice_count) ? index : UINT_MAX;
10147- (
unsigned int) nextVoice:(
unsigned int) index
10149 if (++index >= espeak_voice_count)
10155- (
unsigned int) prevVoice:(
unsigned int) index
10157 if (--index >= espeak_voice_count)
10158 index = espeak_voice_count - 1;
10163- (
unsigned int) setVoice:(
unsigned int) index withGenderM:(BOOL) isMale
10165 if (index == UINT_MAX)
10166 index = [
self voiceNumber:DESC(@"espeak-default-voice")];
10168 if (index < espeak_voice_count)
10170 espeak_VOICE voice = { espeak_voices[index]->name, NULL, NULL, isMale ? 1 : 2 };
10171 espeak_SetVoiceByProperties (&voice);
10179- (void) startSpeakingString:(NSString *) text {}
10181- (void) stopSpeaking {}
10190- (BOOL) pauseMessageVisible
10192 return _pauseMessage;
10196- (void) setPauseMessageVisible:(BOOL)value
10198 _pauseMessage = value;
10202- (BOOL) permanentMessageLog
10204 return _permanentMessageLog;
10208- (void) setPermanentMessageLog:(BOOL)value
10210 _permanentMessageLog = value;
10214- (BOOL) autoMessageLogBg
10216 return _autoMessageLogBg;
10220- (void) setAutoMessageLogBg:(BOOL)value
10222 _autoMessageLogBg = !!value;
10226- (BOOL) permanentCommLog
10228 return _permanentCommLog;
10232- (void) setPermanentCommLog:(BOOL)value
10234 _permanentCommLog = value;
10238- (void) setAutoCommLog:(BOOL)value
10240 _autoCommLog = value;
10244- (BOOL) blockJSPlayerShipProps
10250- (void) setBlockJSPlayerShipProps:(BOOL)value
10263- (void) setUpSettings
10265 [
self resetBeacons];
10267 next_universal_id = 100;
10268 memset(entity_for_uid, 0,
sizeof entity_for_uid);
10270 [
self setMainLightPosition:kZeroVector];
10277 [message_gui autorelease];
10279 initWithPixelSize:NSMakeSize(480, 160)
10286 [comm_log_gui autorelease];
10288 initWithPixelSize:NSMakeSize(360, 120)
10299 [
self setTimeAccelerationFactor:TIME_ACCELERATION_FACTOR_DEFAULT];
10301 universal_time = 0.0;
10302 messageRepeatTime = 0.0;
10303 countdown_messageRepeatTime = 0.0;
10305#if OOLITE_SPEECH_SYNTH
10306 [speechArray autorelease];
10310 [commodities autorelease];
10314 [
self loadDescriptions];
10316 [characters autorelease];
10319 [customSounds autorelease];
10322 [globalSettings autorelease];
10326 [systemManager autorelease];
10329 [screenBackgrounds autorelease];
10333 [roleCategories autorelease];
10336 [autoAIMap autorelease];
10339 [equipmentData autorelease];
10340 [equipmentDataOutfitting autorelease];
10342 equipmentData = [[equipmentTemp sortedArrayUsingFunction:equipmentSort context:NULL] retain];
10343 equipmentDataOutfitting = [[equipmentTemp sortedArrayUsingFunction:equipmentSortOutfitting context:NULL] retain];
10347 [explosionSettings autorelease];
10355 NSMutableDictionary *tmp = [[NSMutableDictionary alloc] initWithCapacity:[commodities count]];
10357 foreach (type, [commodities goods])
10359 ShipEntity *container = [
self newShipWithRole:@"oolite-template-cargopod"];
10362 [tmp setObject:container forKey:type];
10363 [container release];
10365 [cargoPods release];
10366 cargoPods = [[NSDictionary alloc] initWithDictionary:tmp];
10373 NSMutableArray *badEntities =
nil;
10377 for (i = 0; i < n_entities; i++)
10379 entity = sortedEntities[i];
10380 if ([entity sessionID] != _sessionID)
10382 OOLogERR(
@"universe.sessionIDs.verify.failed",
@"Invalid entity %@ (came from session %lu, current session is %lu).", [entity shortDescription], [entity sessionID], _sessionID);
10383 if (badEntities ==
nil) badEntities = [NSMutableArray array];
10384 [badEntities addObject:entity];
10388 foreach (entity, badEntities)
10390 [
self removeEntity:entity];
10397- (BOOL) reinitAndShowDemo:(BOOL) showDemo
10401 assert(player !=
nil);
10412 [
self removeAllEntitiesExceptPlayer];
10425 [[
self gameController] setGamePaused:NO];
10426 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
10427 [PLAYER setSpeed:0.0];
10429 [
self loadDescriptions];
10430 [
self loadScenarios];
10432 [missiontext autorelease];
10438 [demo_ships release];
10440 demo_ship_index = 0;
10441 demo_ship_subindex = 0;
10444 breakPatternCounter = 0;
10447 cachedPlanet =
nil;
10448 cachedStation =
nil;
10450 [
self setUpSettings];
10455 [
self setUpCargoPods];
10457 if (![player setUpAndConfirmOK:YES])
10466 [
self addEntity:player];
10468 [[
self gameController] setPlayerFileToLoad:nil];
10470 [
self setUpInitialUniverse];
10473 [[
self station] initialiseLocalMarket];
10496 [
self populateNormalSpace];
10507 [
self verifyEntitySessionIDs];
10519 if (activeWormholes) [activeWormholes autorelease];
10520 activeWormholes = [[NSMutableArray arrayWithCapacity:16] retain];
10521 if (characterPool) [characterPool autorelease];
10522 characterPool = [[NSMutableArray arrayWithCapacity:256] retain];
10526 [
self setGalaxyTo: [player
galaxyNumber] andReinit:YES];
10538 [
self setDockingClearanceProtocolActive:
10539 [[
self currentSystemData] oo_boolForKey:@"stations_require_docking_clearance" defaultValue:YES]];
10541 [
self enterGUIViewModeWithMouseInteraction:NO];
10553- (Vector) randomPlaceWithinScannerFrom:(Vector)pos alongRoute:(Vector)route withOffset:(
double)offset
10555 pos.x +=
offset * route.
x + [
self randomDistanceWithinScanner];
10556 pos.y +=
offset * route.
y + [
self randomDistanceWithinScanner];
10557 pos.z +=
offset * route.z + [
self randomDistanceWithinScanner];
10563- (HPVector) fractionalPositionFrom:(HPVector)point0 to:(HPVector)point1 withFraction:(
double)routeFraction
10565 if (routeFraction == NSNotFound) routeFraction =
randf();
10567 point1 = OOHPVectorInterpolate(point0, point1, routeFraction);
10577- (BOOL)doRemoveEntity:(
Entity *)entity
10580 if ([entity canCollide])
10582 doLinkedListMaintenanceThisUpdate = YES;
10590 entity_for_uid[old_id] =
nil;
10600 if (sortedEntities[index] != entity)
10602 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity:%@ ENTITY IS NOT IN THE RIGHT PLACE IN THE ZERO_DISTANCE SORTED LIST -- FIXING...", entity);
10605 for (i = 0; (i < n_entities)&&(index == -1); i++)
10606 if (sortedEntities[i] == entity)
10609 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity:%@ ENTITY IS NOT IN THE ZERO_DISTANCE SORTED LIST -- CONTINUING...", entity);
10613 while ((
unsigned)index < n_entities)
10615 while (((
unsigned)index + n < n_entities)&&(sortedEntities[index + n] == entity))
10634 sortedEntities[index] = sortedEntities[index + n];
10635 if (sortedEntities[index])
10637 sortedEntities[index]->zero_index = index;
10642 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity: REMOVED %d EXTRA COPIES OF %@ FROM THE ZERO_DISTANCE SORTED LIST", n - 1, entity);
10646 sortedEntities[n_entities] =
nil;
10653 if ([entities containsObject:entity])
10656 if ([entity isBreakPattern] && ![entity isVisualEffect])
10658 breakPatternCounter--;
10661 if ([entity isShip])
10664 [
self clearBeacon:se];
10666 if ([entity isWaypoint])
10669 [
self clearBeacon:wp];
10671 if ([entity isVisualEffect])
10674 [
self clearBeacon:ve];
10677 if ([entity isWormhole])
10679 [activeWormholes removeObject:entity];
10681 else if ([entity isPlanet])
10683 [allPlanets removeObject:entity];
10686 [entities removeObject:entity];
10694static void PreloadOneSound(NSString *soundName)
10696 if (![soundName hasPrefix:
@"["] && ![soundName hasSuffix:@"]"])
10703- (void) preloadSounds
10706 NSString *key =
nil;
10709 id object = [customSounds objectForKey:key];
10710 if([
object isKindOfClass:[NSString class]])
10712 PreloadOneSound(
object);
10714 else if([
object isKindOfClass:[NSArray class]] && [object
count] > 0)
10716 NSString *soundName =
nil;
10717 foreach (soundName,
object)
10719 if ([soundName isKindOfClass:[NSString class]])
10721 PreloadOneSound(soundName);
10728 PreloadOneSound(
@"afterburner1.ogg");
10734 NSAutoreleasePool *pool =
nil;
10736 while ([activeWormholes
count])
10738 pool = [[NSAutoreleasePool alloc] init];
10744 if (![whole isScanned] &&
10745 NSEqualPoints([
PLAYER galaxy_coordinates], [whole destinationCoordinates]) )
10750 [activeWormholes removeObjectAtIndex:0];
10752 @catch (NSException *exception)
10754 OOLog(
kOOLogException,
@"Squashing exception during wormhole unpickling (%@: %@).", [exception name], [exception reason]);
10761- (NSString *)chooseStringForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary
10763 id object = [dictionary objectForKey:key];
10764 if ([
object isKindOfClass:[NSString class]]) return object;
10765 else if ([
object isKindOfClass:[NSArray class]] && [object
count] > 0) return [object oo_stringAtIndex:
Ranrot() % [object
count]];
10770#if OO_LOCALIZATION_TOOLS
10773- (void) dumpDebugGraphViz
10775 if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"universe-dump-debug-graphviz"])
10777 [
self dumpSystemDescriptionGraphViz];
10782- (void) dumpSystemDescriptionGraphViz
10784 NSMutableString *graphViz =
nil;
10785 NSArray *systemDescriptions =
nil;
10786 NSArray *thisDesc =
nil;
10787 NSUInteger i,
count, j, subCount;
10788 NSString *descLine =
nil;
10789 NSArray *curses =
nil;
10790 NSString *label =
nil;
10791 NSDictionary *keyMap =
nil;
10797 graphViz = [NSMutableString stringWithString:
10798 @"// System description grammar:\n\n"
10799 "digraph system_descriptions\n"
10801 "\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"
10802 "\tedge [arrowhead=dot]\n"
10803 "\tnode [shape=none height=0.2 width=3 fontname=Helvetica]\n\t\n"];
10805 systemDescriptions = [[
self descriptions] oo_arrayForKey:@"system_description"];
10806 count = [systemDescriptions count];
10809 descLine =
DESC(
@"system-description-string");
10811 [graphViz appendFormat:@"\tsystem_description_string [label=\"%@\" shape=ellipse]\n", EscapedGraphVizString(label)];
10812 [
self addNumericRefsInString:descLine
10813 toGraphViz:graphViz
10814 fromNode:@"system_description_string"
10816 [graphViz appendString:@"\t\n"];
10819 [graphViz appendString:
10820 @"\tpercent_I [label=\"%I\\nInhabitants\" shape=diamond]\n"
10821 "\tpercent_H [label=\"%H\\nSystem name\" shape=diamond]\n"
10822 "\tpercent_RN [label=\"%R/%N\\nRandom name\" shape=diamond]\n"
10823 "\tpercent_J [label=\"%J\\nNumbered system name\" shape=diamond]\n"
10824 "\tpercent_G [label=\"%G\\nNumbered system name in chart number\" shape=diamond]\n\t\n"];
10827 [graphViz appendString:@"\tsubgraph cluster_thargoid_curses\n\t{\n\t\tlabel = \"Thargoid curses\"\n"];
10828 curses = [[
self descriptions] oo_arrayForKey:@"thargoid_curses"];
10829 subCount = [curses count];
10830 for (j = 0; j < subCount; ++j)
10833 [graphViz appendFormat:@"\t\tthargoid_curse_%lu [label=\"%@\"]\n", j, EscapedGraphVizString(label)];
10835 [graphViz appendString:@"\t}\n"];
10836 for (j = 0; j < subCount; ++j)
10838 [
self addNumericRefsInString:[curses oo_stringAtIndex:j]
10839 toGraphViz:graphViz
10840 fromNode:[NSString stringWithFormat:@"thargoid_curse_%lu", j]
10843 [graphViz appendString:@"\t\n"];
10847 for (i = 0; i <
count; ++i)
10850 label = [keyMap objectForKey:[NSString stringWithFormat:@"%lu", i]];
10851 if (label ==
nil) label = [NSString stringWithFormat:
@"[%lu]", i];
10852 else label = [NSString stringWithFormat:@"[%lu] (%@)", i, label];
10854 [graphViz appendFormat:@"\tsubgraph cluster_%lu\n\t{\n\t\tlabel=\"%@\"\n", i, EscapedGraphVizString(label)];
10856 thisDesc = [systemDescriptions oo_arrayAtIndex:i];
10857 subCount = [thisDesc count];
10858 for (j = 0; j < subCount; ++j)
10861 [graphViz appendFormat:@"\t\tn%lu_%lu [label=\"\\\"%@\\\"\"]\n", i, j, EscapedGraphVizString(label)];
10864 [graphViz appendString:@"\t}\n"];
10866 [graphViz appendString:@"\t\n"];
10869 for (i = 0; i !=
count; ++i)
10871 thisDesc = [systemDescriptions oo_arrayAtIndex:i];
10872 subCount = [thisDesc count];
10873 for (j = 0; j != subCount; ++j)
10875 descLine = [thisDesc oo_stringAtIndex:j];
10876 [
self addNumericRefsInString:descLine
10877 toGraphViz:graphViz
10878 fromNode:[NSString stringWithFormat:@"n%lu_%lu", i, j]
10884 [graphViz appendString:@"\t}\n"];
10890- (void) addNumericRefsInString:(NSString *)string toGraphViz:(NSMutableString *)graphViz fromNode:(NSString *)fromNode nodeCount:(NSUInteger)nodeCount
10892 NSString *index =
nil;
10893 NSInteger start, end;
10894 NSRange remaining, subRange;
10897 remaining = NSMakeRange(0, [
string length]);
10901 subRange = [string rangeOfString:@"[" options:NSLiteralSearch range:remaining];
10902 if (subRange.location == NSNotFound)
break;
10903 start = subRange.location + subRange.length;
10904 remaining.length -= start - remaining.location;
10905 remaining.location = start;
10907 subRange = [string rangeOfString:@"]" options:NSLiteralSearch range:remaining];
10908 if (subRange.location == NSNotFound)
break;
10909 end = subRange.location;
10910 remaining.length -= end - remaining.location;
10911 remaining.location = end;
10913 index = [string substringWithRange:NSMakeRange(start, end - start)];
10914 i = [index intValue];
10917 [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];
10920 if ([
string rangeOfString:
@"%I"].location != NSNotFound)
10922 [graphViz appendFormat:@"\t%@ -> percent_I [color=\"0,0,0.25\"]\n", fromNode];
10924 if ([
string rangeOfString:
@"%H"].location != NSNotFound)
10926 [graphViz appendFormat:@"\t%@ -> percent_H [color=\"0,0,0.45\"]\n", fromNode];
10928 if ([
string rangeOfString:
@"%R"].location != NSNotFound || [string rangeOfString:
@"%N"].location != NSNotFound)
10930 [graphViz appendFormat:@"\t%@ -> percent_RN [color=\"0,0,0.65\"]\n", fromNode];
10934 if ([
string rangeOfString:
@"%J"].location != NSNotFound)
10936 [graphViz appendFormat:@"\t%@ -> percent_J [color=\"0,0,0.75\"]\n", fromNode];
10939 if ([
string rangeOfString:
@"%G"].location != NSNotFound)
10941 [graphViz appendFormat:@"\t%@ -> percent_G [color=\"0,0,0.85\"]\n", fromNode];
10949 NSArray *arguments =
nil;
10950 NSEnumerator *argEnum =
nil;
10951 NSString *arg =
nil;
10952 BOOL compileSysDesc = NO, exportSysDesc = NO, xml = NO;
10954 arguments = [[NSProcessInfo processInfo] arguments];
10956 for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
10958 if ([arg isEqual:
@"--compile-sysdesc"]) compileSysDesc = YES;
10959 else if ([arg isEqual:
@"--export-sysdesc"]) exportSysDesc = YES;
10960 else if ([arg isEqual:
@"--xml"]) xml = YES;
10961 else if ([arg isEqual:
@"--openstep"]) xml = NO;
10972- (void) prunePreloadingPlanetMaterials
10976 NSUInteger i = [_preloadingPlanetMaterials count];
10979 if ([[_preloadingPlanetMaterials objectAtIndex:i] isFinishedLoading])
10981 [_preloadingPlanetMaterials removeObjectAtIndex:i];
10989- (void) loadConditionScripts
10991 [conditionScripts autorelease];
10992 conditionScripts = [[NSMutableDictionary alloc] init];
11002- (void) addConditionScripts:(NSEnumerator *)scripts
11004 NSString *scriptname =
nil;
11005 while ((scriptname = [scripts nextObject]))
11007 if ([conditionScripts objectForKey:scriptname] ==
nil)
11012 [conditionScripts setObject:script forKey:scriptname];
11019- (
OOJSScript*) getConditionScript:(NSString *)scriptname
11021 return [conditionScripts objectForKey:scriptname];
11027@implementation OOSound (OOCustomSounds)
11029+ (id) soundWithCustomSoundKey:(NSString *)key
11031 NSString *fileName = [UNIVERSE soundNameForCustomSoundKey:key];
11032 if (fileName ==
nil)
return nil;
11037- (id) initWithCustomSoundKey:(NSString *)key
11046@implementation OOSoundSource (OOCustomSounds)
11048+ (id) sourceWithCustomSoundKey:(NSString *)key
11050 return [[[
self alloc] initWithCustomSoundKey:key] autorelease];
11054- (id) initWithCustomSoundKey:(NSString *)key
11057 if (theSound !=
nil)
11059 self = [
self initWithSound:theSound];
11070- (void) playCustomSoundWithKey:(NSString *)key
11073 if (theSound !=
nil) [
self playSound:theSound];
11080 NSDictionary *one = (NSDictionary *)a;
11081 NSDictionary *two = (NSDictionary *)b;
11082 int pri_one = [one oo_intForKey:@"priority" defaultValue:100];
11083 int pri_two = [two oo_intForKey:@"priority" defaultValue:100];
11084 if (pri_one < pri_two)
return NSOrderedAscending;
11085 if (pri_one > pri_two)
return NSOrderedDescending;
11086 return NSOrderedSame;
11092 NSArray *one = (NSArray *)a;
11093 NSArray *two = (NSArray *)b;
11097 OOCreditsQuantity comp1 = [[one oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000];
11098 OOCreditsQuantity comp2 = [[two oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000];
11099 if (comp1 < comp2)
return NSOrderedAscending;
11100 if (comp1 > comp2)
return NSOrderedDescending;
11102 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11103 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11104 if (comp1 < comp2)
return NSOrderedAscending;
11105 if (comp1 > comp2)
return NSOrderedDescending;
11107 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11108 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11109 if (comp1 < comp2)
return NSOrderedAscending;
11110 if (comp1 > comp2)
return NSOrderedDescending;
11112 return NSOrderedSame;
11118 NSArray *one = (NSArray *)a;
11119 NSArray *two = (NSArray *)b;
11123 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]];
11124 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]];
11125 if (comp1 < comp2)
return NSOrderedAscending;
11126 if (comp1 > comp2)
return NSOrderedDescending;
11128 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11129 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11130 if (comp1 < comp2)
return NSOrderedAscending;
11131 if (comp1 > comp2)
return NSOrderedDescending;
11133 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11134 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11135 if (comp1 < comp2)
return NSOrderedAscending;
11136 if (comp1 > comp2)
return NSOrderedDescending;
11138 return NSOrderedSame;
11144 NSString *result = [UNIVERSE descriptionForKey:key];
11145 if (result ==
nil) result = key;
11153 NSArray *conditions = [[UNIVERSE descriptions] oo_arrayForKey:@"plural-rules"];
11156 NSString *tmp = [UNIVERSE descriptionForKey:key];
11159 static NSMutableSet *warned =
nil;
11161 if (![warned containsObject:tmp])
11163 OOLogWARN(
@"localization.plurals",
@"'%@' found in descriptions.plist, should be '%@%%0'. Localization data needs updating.",key,key);
11164 if (warned ==
nil) warned = [[NSMutableSet alloc] init];
11165 [warned addObject:tmp];
11169 if (conditions ==
nil)
11179 for (index = i = 0; i < [conditions count]; ++index, ++i)
11181 const char *cond = [[conditions oo_stringAtIndex:i] UTF8String];
11185 long int input =
count;
11188 while (isspace (*cond))
11193 while (isspace (*cond))
11196 char command = *cond++;
11208 long int param = strtol(cond, (
char **)&cond, 10);
11223 if (flag ^ (input == param))
11227 if (flag ^ (input != param))
11232 if (flag ^ (input < param))
11236 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 wasAddedToUniverse()
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()
OOUniversalID shadingEntityID
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 setJumpCause:(NSString *value)
void setDockedAtMainStation()
void setPreviousSystemID:(OOSystemID sid)
OOMatrix customViewMatrix
void runUnsanitizedScriptActions:allowingAIMethods:withContextName:forTarget:(NSArray *unsanitizedActions,[allowingAIMethods] BOOL allowAIMethods,[withContextName] NSString *contextName,[forTarget] ShipEntity *target)
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
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