27#import "MyOpenGLView.h"
98#if OO_LOCALIZATION_TOOLS
109#define DEMO2_VANISHING_DISTANCE 650.0
110#define DEMO2_FLY_IN_STAGE_TIME 0.4
113#define MAX_NUMBER_OF_ENTITIES 200
114#define STANDARD_STATION_ROLL 0.4
116#define LANE_WIDTH 51200.0
127 1.0f, 1.0f, 1.0f, 1.0f,
128 1.0f, -1.0f, 1.0f, 0.0f,
129 -1.0f, -1.0f, 0.0f, 0.0f,
130 -1.0f, 1.0f, 0.0f, 1.0f
151#undef CACHE_ROUTE_FROM_SYSTEM_RESULTS
161+ (instancetype) elementWithLocation:(
OOSystemID) location parent:(
OOSystemID)parent cost:(
double) cost distance:(
double) distance time:(
double) time jumps:(
int) jumps;
173+ (instancetype) elementWithLocation:(
OOSystemID) location parent:(
OOSystemID) parent cost:(
double) cost distance:(
double) distance time:(
double) time jumps:(
int) jumps
184 return [r autorelease];
197@interface Universe (OOPrivate)
199- (void) initTargetFramebufferWithViewSize:(NSSize)viewSize;
201- (void) resizeTargetFramebufferWithViewSize:(NSSize)viewSize;
205- (BOOL) doRemoveEntity:(
Entity *)entity;
208- (HPVector) fractionalPositionFrom:(HPVector)point0 to:(HPVector)point1 withFraction:(
double)routeFraction;
212- (NSString *)chooseStringForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary;
214#if OO_LOCALIZATION_TOOLS
216- (void) dumpDebugGraphViz;
217- (void) dumpSystemDescriptionGraphViz;
219- (void) addNumericRefsInString:(NSString *)string toGraphViz:(NSMutableString *)graphViz fromNode:(NSString *)fromNode nodeCount:(NSUInteger)nodeCount;
229- (void) prunePreloadingPlanetMaterials;
235- (void) setFirstBeacon:(
Entity <OOBeaconEntity> *)beacon;
236- (void) setLastBeacon:(
Entity <OOBeaconEntity> *)beacon;
244- (Vector) randomPlaceWithinScannerFrom:(Vector)pos alongRoute:(Vector)route withOffset:(
double)offset;
263static GLfloat
sun_off[4] = {0.0, 0.0, 0.0, 1.0};
266#define DOCKED_AMBIENT_LEVEL 0.2f
267#define DOCKED_ILLUM_LEVEL 0.7f
274#define SUN_AMBIENT_INFLUENCE 0.75
276#define SKY_AMBIENT_ADJUSTMENT 0.0625
283- (void) setBloom: (BOOL)newBloom
290 return _currentPostFX;
293- (void) setCurrentPostFX: (
int) newCurrentPostFX
302 _colorblindMode = newCurrentPostFX;
305 _currentPostFX = newCurrentPostFX;
309- (void) terminatePostFX:(
int)postFX
311 if ([
self currentPostFX] == postFX)
313 [
self setCurrentPostFX:[
self colorblindMode]];
317- (
int) nextColorblindMode:(
int) index
325- (
int) prevColorblindMode:(
int) index
333- (
int) colorblindMode
335 return _colorblindMode;
338- (void) initTargetFramebufferWithViewSize:(NSSize)viewSize
341 OOGL(glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE));
342 OOGL(glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE));
343 OOGL(glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE));
346 OOGL(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &defaultDrawFBO));
348 GLint previousProgramID;
349 OOGL(glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgramID));
350 GLint previousTextureID;
351 OOGL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureID));
353 OOGL(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previousVAO));
354 GLint previousArrayBuffer;
355 OOGL(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousArrayBuffer));
356 GLint previousElementBuffer;
357 OOGL(glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &previousElementBuffer));
360 OOGL(glGenFramebuffers(1, &msaaFramebufferID));
361 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
364 OOGL(glGenTextures(1, &msaaTextureID));
365 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
366 OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, GL_TRUE));
367 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
368 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID, 0));
371 OOGL(glGenRenderbuffers(1, &msaaDepthBufferID));
372 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
373 OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
374 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
375 OOGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaaDepthBufferID));
377 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
379 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Multisample framebuffer not complete");
383 OOGL(glGenFramebuffers(1, &targetFramebufferID));
384 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
387 OOGL(glGenTextures(1, &targetTextureID));
388 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
389 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
390 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
391 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
394 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTextureID, 0));
397 OOGL(glGenRenderbuffers(1, &targetDepthBufferID));
398 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, targetDepthBufferID));
399 OOGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
400 OOGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, targetDepthBufferID));
402 GLenum attachment[1] = { GL_COLOR_ATTACHMENT0 };
403 OOGL(glDrawBuffers(1, attachment));
405 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
407 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Framebuffer not complete");
410 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
412 targetFramebufferSize = viewSize;
420 OOGL(glGenFramebuffers(1, &passthroughFramebufferID));
421 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, passthroughFramebufferID));
424 OOGL(glGenTextures(2, passthroughTextureID));
425 for (
unsigned int i = 0; i < 2; i++)
427 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[i]));
428 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
429 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
430 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
433 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, passthroughTextureID[i], 0));
436 GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
437 OOGL(glDrawBuffers(2, attachments));
439 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
441 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Passthrough framebuffer not complete");
443 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
446 OOGL(glGenFramebuffers(2, pingpongFBO));
447 OOGL(glGenTextures(2, pingpongColorbuffers));
448 for (
unsigned int i = 0; i < 2; i++)
450 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]));
451 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]));
452 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
453 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
454 OOGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
457 OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongColorbuffers[i], 0));
459 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
461 OOLogERR(
@"initTargetFramebufferWithViewSize.result",
@"%@",
@"***** Error: Pingpong framebuffers not complete");
464 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
478 textureProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-texture.vertex"
479 fragmentShaderName:@"oolite-texture.fragment"
480 prefix:@"#version 330\n"
481 attributeBindings:[NSDictionary dictionary]] retain];
483 blurProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-blur.vertex"
484 fragmentShaderName:@"oolite-blur.fragment"
485 prefix:@"#version 330\n"
486 attributeBindings:[NSDictionary dictionary]] retain];
488 finalProgram = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-final.vertex"
490 fragmentShaderName:[[UNIVERSE gameView] hdrOutput] ? @"oolite-final-hdr.fragment" : @"oolite-final.fragment"
492 fragmentShaderName:@"oolite-final.fragment"
494 prefix:@"#version 330\n"
495 attributeBindings:[NSDictionary dictionary]] retain];
498 OOGL(glGenVertexArrays(1, &quadTextureVAO));
499 OOGL(glGenBuffers(1, &quadTextureVBO));
500 OOGL(glGenBuffers(1, &quadTextureEBO));
502 OOGL(glBindVertexArray(quadTextureVAO));
504 OOGL(glBindBuffer(GL_ARRAY_BUFFER, quadTextureVBO));
507 OOGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadTextureEBO));
510 OOGL(glEnableVertexAttribArray(0));
512 OOGL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float), (
void*)0));
513 OOGL(glEnableVertexAttribArray(1));
515 OOGL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float), (
void*)(2 *
sizeof(
float))));
519 OOGL(glUseProgram(previousProgramID));
520 OOGL(glBindTexture(GL_TEXTURE_2D, previousTextureID));
521 OOGL(glBindVertexArray(previousVAO));
522 OOGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, previousElementBuffer));
523 OOGL(glBindBuffer(GL_ARRAY_BUFFER, previousArrayBuffer));
530 OOGL(glDeleteTextures(1, &msaaTextureID));
531 OOGL(glDeleteTextures(1, &targetTextureID));
532 OOGL(glDeleteTextures(2, passthroughTextureID));
533 OOGL(glDeleteTextures(2, pingpongColorbuffers));
534 OOGL(glDeleteRenderbuffers(1, &msaaDepthBufferID));
535 OOGL(glDeleteRenderbuffers(1, &targetDepthBufferID));
536 OOGL(glDeleteFramebuffers(1, &msaaFramebufferID));
537 OOGL(glDeleteFramebuffers(1, &targetFramebufferID));
538 OOGL(glDeleteFramebuffers(2, pingpongFBO));
539 OOGL(glDeleteFramebuffers(1, &passthroughFramebufferID));
540 OOGL(glDeleteVertexArrays(1, &quadTextureVAO));
541 OOGL(glDeleteBuffers(1, &quadTextureVBO));
542 OOGL(glDeleteBuffers(1, &quadTextureEBO));
543 [textureProgram release];
544 [blurProgram release];
545 [finalProgram release];
549- (void) resizeTargetFramebufferWithViewSize:(NSSize)viewSize
553 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
554 OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, GL_TRUE));
555 OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
558 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
559 OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
560 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
563 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
564 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
565 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
567 for (i = 0; i < 2; i++)
569 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]));
570 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
571 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
574 for (i = 0; i < 2; i++)
576 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[i]));
577 OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei)viewSize.width, (GLsizei)viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
578 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
582 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, targetDepthBufferID));
583 OOGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, (GLsizei)viewSize.width, (GLsizei)viewSize.height));
584 OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
586 targetFramebufferSize.width = viewSize.width;
587 targetFramebufferSize.height = viewSize.height;
595 OOGL(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previousFBO));
596 GLint previousProgramID;
597 OOGL(glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgramID));
598 GLint previousTextureID;
599 OOGL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureID));
601 OOGL(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previousVAO));
602 GLint previousActiveTexture;
603 OOGL(glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture));
605 OOGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
607 OOGL(glDisable(GL_BLEND));
609 GLhandleARB program = [textureProgram program];
610 GLhandleARB blur = [blurProgram program];
611 GLhandleARB
final = [finalProgram program];
612 NSSize viewSize = [gameView backingViewSize];
613 float fboResolution[2] = {viewSize.width, viewSize.height};
615 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, passthroughFramebufferID));
616 OOGL(glClear(GL_COLOR_BUFFER_BIT));
618 OOGL(glUseProgram(program));
619 OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
620 OOGL(glUniform1i(glGetUniformLocation(program,
"image"), 0));
623 OOGL(glBindVertexArray(quadTextureVAO));
624 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
625 OOGL(glBindVertexArray(0));
627 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
630 BOOL horizontal = YES, firstIteration = YES;
631 unsigned int amount = [
self bloom] ? 10 : 0;
632 OOGL(glUseProgram(blur));
633 for (
unsigned int i = 0; i < amount; i++)
635 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]));
636 OOGL(glUniform1i(glGetUniformLocation(blur,
"horizontal"), horizontal));
637 OOGL(glActiveTexture(GL_TEXTURE0));
639 OOGL(glBindTexture(GL_TEXTURE_2D, firstIteration ? passthroughTextureID[1] : pingpongColorbuffers[!horizontal]));
640 OOGL(glUniform1i(glGetUniformLocation([blurProgram program],
"imageIn"), 0));
641 OOGL(glBindVertexArray(quadTextureVAO));
642 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
643 OOGL(glBindVertexArray(0));
644 horizontal = !horizontal;
647 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
650 OOGL(glUseProgram(
final));
652 OOGL(glActiveTexture(GL_TEXTURE0));
653 OOGL(glBindTexture(GL_TEXTURE_2D, passthroughTextureID[0]));
654 OOGL(glUniform1i(glGetUniformLocation(
final,
"scene"), 0));
655 OOGL(glUniform1i(glGetUniformLocation(
final,
"bloom"), [
self bloom]));
656 OOGL(glUniform1f(glGetUniformLocation(
final,
"uTime"), [
self getTime]));
657 OOGL(glUniform2fv(glGetUniformLocation(
final,
"uResolution"), 1, fboResolution));
658 OOGL(glUniform1i(glGetUniformLocation(
final,
"uPostFX"), [
self currentPostFX]));
660 if([gameView hdrOutput])
662 OOGL(glUniform1f(glGetUniformLocation(
final,
"uMaxBrightness"), [gameView hdrMaxBrightness]));
663 OOGL(glUniform1f(glGetUniformLocation(
final,
"uPaperWhiteBrightness"), [gameView hdrPaperWhiteBrightness]));
664 OOGL(glUniform1i(glGetUniformLocation(
final,
"uHDRToneMapper"), [gameView hdrToneMapper]));
667 OOGL(glUniform1i(glGetUniformLocation(
final,
"uSDRToneMapper"), [gameView sdrToneMapper]));
669 OOGL(glActiveTexture(GL_TEXTURE1));
670 OOGL(glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]));
671 OOGL(glUniform1i(glGetUniformLocation(
final,
"bloomBlur"), 1));
672 OOGL(glUniform1f(glGetUniformLocation(
final,
"uSaturation"), [gameView colorSaturation]));
674 OOGL(glBindVertexArray(quadTextureVAO));
675 OOGL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
679 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
682 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, previousFBO));
683 OOGL(glActiveTexture(previousActiveTexture));
684 OOGL(glBindTexture(GL_TEXTURE_2D, previousTextureID));
685 OOGL(glUseProgram(previousProgramID));
686 OOGL(glBindVertexArray(previousVAO));
687 OOGL(glEnable(GL_BLEND));
695 [NSException raise:NSInternalInconsistencyException format:@"%s: expected only one Universe to exist at a time.", __PRETTY_FUNCTION__];
701 if (
self ==
nil)
return nil;
707 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
711 useAddOns = [[NSString alloc] initWithString:SCENARIO_OXP_DEFINITION_ALL];
713 [
self setGameView:inGameView];
716 allPlanets = [[NSMutableArray alloc] init];
717 allStations = [[NSMutableSet alloc] init];
724 [
self setDetailLevelDirectly:[prefs oo_intForKey:@"detailLevel"
727 [
self initTargetFramebufferWithViewSize:[gameView backingViewSize]];
734#if OOLITE_SPEECH_SYNTH
735 OOLog(
@"speech.synthesis",
@"Spoken messages are %@.", ([prefs oo_boolForKey:
@"speech_on" defaultValue:NO] ?
@"on" :
@"off"));
742 [
self loadDescriptions];
746 [
self loadScenarios];
748 autoSave = [prefs oo_boolForKey:@"autosave" defaultValue:NO];
749 wireframeGraphics = [prefs oo_boolForKey:@"wireframe-graphics" defaultValue:NO];
750 doProcedurallyTexturedPlanets = [prefs oo_boolForKey:@"procedurally-textured-planets" defaultValue:YES];
751 [inGameView
setMsaa:[prefs oo_boolForKey:@"anti-aliasing" defaultValue:NO]];
752 OOLog(
@"MSAA.setup",
@"Multisample anti-aliasing %@requested.", [inGameView msaa] ?
@"" :
@"not ");
753 [inGameView
setFov:OOClamp_0_max_f([prefs oo_floatForKey:@"fov-value" defaultValue:57.2f], MAX_FOV_DEG)
fromFraction:NO];
756 [
self setECMVisualFXEnabled:[prefs oo_boolForKey:@"ecm-visual-fx" defaultValue:YES]];
759#if OOLITE_SPEECH_SYNTH
761 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
771 OOLog(
@"speech.setup.begin",
@"Starting to set up speech synthesizer.");
772 NSSpeechSynthesizer *synth = [[NSSpeechSynthesizer alloc] init];
773 OOLog(
@"speech.setup.end",
@"Finished setting up speech synthesizer.");
774 speechSynthesizer = synth;
778 if (!SDL_getenv(
"ESPEAK_DATA_PATH"))
780 espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 100, [[
ResourceManager builtInPath] UTF8String], 0);
784 espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 100, NULL, 0);
786 espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_NONE, 0);
787 espeak_SetParameter(espeakVOLUME, volume, 0);
788 espeak_voices = espeak_ListVoices(NULL);
789 for (espeak_voice_count = 0;
790 espeak_voices[espeak_voice_count];
791 ++espeak_voice_count)
801 entities = [[NSMutableArray arrayWithCapacity:MAX_NUMBER_OF_ENTITIES] retain];
811 waypoints = [[NSMutableDictionary alloc] init];
813 [
self setUpSettings];
824 [
self setUpCargoPods];
828 [
self addEntity:player];
833 [
self setUpInitialUniverse];
836 entitiesDeadThisUpdate = [[NSMutableSet alloc] init];
837 framesDoneThisUpdate = 0;
847 [
self populateNormalSpace];
851#if OO_LOCALIZATION_TOOLS
852 [
self runLocalizationTools];
854 [
self dumpDebugGraphViz];
869 [currentMessage release];
872 [message_gui release];
873 [comm_log_gui release];
877 [commodities release];
879 [_descriptions release];
880 [characters release];
881 [customSounds release];
882 [globalSettings release];
883 [systemManager release];
884 [missiontext release];
885 [equipmentData release];
886 [equipmentDataOutfitting release];
887 [demo_ships release];
889 [screenBackgrounds release];
891 [populatorSettings release];
892 [system_repopulator release];
893 [allPlanets release];
894 [allStations release];
895 [explosionSettings release];
897 [activeWormholes release];
898 [characterPool release];
899 [universeRegion release];
907 for (i = 0; i < 256; i++) [system_names[i] release];
909 [entitiesDeadThisUpdate release];
913#if OOLITE_SPEECH_SYNTH
914 [speechArray release];
916 [speechSynthesizer release];
921 [conditionScripts release];
923 [
self deleteOpenGLObjects];
929- (NSUInteger) sessionID
937 return _doingStartUp;
941- (BOOL) doProcedurallyTexturedPlanets
943 return doProcedurallyTexturedPlanets;
947- (void) setDoProcedurallyTexturedPlanets:(BOOL) value
949 doProcedurallyTexturedPlanets = !!value;
950 [[NSUserDefaults standardUserDefaults] setBool:doProcedurallyTexturedPlanets forKey:@"procedurally-textured-planets"];
954- (NSString *) useAddOns
960- (BOOL) setUseAddOns:(NSString *) newUse fromSaveGame:(BOOL) saveGame
962 return [
self setUseAddOns:newUse fromSaveGame:saveGame forceReinit:NO];
966- (BOOL) setUseAddOns:(NSString *) newUse fromSaveGame:(BOOL) saveGame forceReinit:(BOOL)force
968 if (!force && [newUse isEqualToString:useAddOns])
973 useAddOns = [newUse retain];
975 return [
self reinitAndShowDemo:!saveGame];
980- (NSUInteger) entityCount
982 return [entities count];
987- (void) debugDumpEntities
990 int show_count = n_entities;
994 OOLog(
@"universe.objectDump",
@"DEBUG: Entity Dump - [entities count] = %llu,\tn_entities = %u", [entities
count], n_entities);
997 for (i = 0; i < show_count; i++)
999 OOLog(
@"universe.objectDump",
@"Ent:%4u %@", i, [sortedEntities[i] descriptionForObjDump]);
1003 if ([entities
count] != n_entities)
1005 OOLog(
@"universe.objectDump",
@"entities = %@", [entities description]);
1010- (NSArray *) entityList
1012 return [NSArray arrayWithArray:entities];
1022 [
self setPauseMessageVisible:NO];
1023 NSString *pauseKey = [PLAYER keyBindingDescription2:@"key_pausebutton"];
1025 if ([player status] == STATUS_DOCKED)
1027 if ([gui setForegroundTextureKey:
@"paused_docked_overlay"])
1029 [gui drawGUI:1.0 drawCursor:NO];
1033 [
self setPauseMessageVisible:YES];
1034 [
self addMessage:OOExpandKey(@"game-paused-docked", pauseKey) forCount:1.0];
1039 if ([player guiScreen] != GUI_SCREEN_MAIN && [gui setForegroundTextureKey:
@"paused_overlay"])
1041 [gui drawGUI:1.0 drawCursor:NO];
1045 [
self setPauseMessageVisible:YES];
1046 [
self addMessage:OOExpandKey(@"game-paused", pauseKey) forCount:1.0];
1050 [[
self gameController] setGamePaused:YES];
1055 OOLog(
@"universe.quit",
@"%@",
@"Quit command received by Universe.");
1056 [[
self gameController] exitAppWithContext:@"Universe Request"];
1069 ShipScriptEvent(context, player,
"shipWillEnterWitchspace", STRING_TO_JSVAL(JS_InternString(context, [[player jumpCause] UTF8String])), INT_TO_JSVAL(dest));
1072 [
self allShipsDoScriptEvent:OOJSID("playerWillEnterWitchspace") andReactToAIMessage:@"PLAYER WITCHSPACE"];
1079 [
self removeAllEntitiesExceptPlayer];
1084 if (![wormhole withMisjump])
1087 [
self setSystemTo: dest];
1090 [
self populateNormalSpace];
1098 [
self setUpWitchspaceBetweenSystem:[wormhole
origin] andSystem:[wormhole
destination]];
1107 [UNIVERSE setSkyColorRed:0.0f
1112 [
self setWitchspaceBreakPattern:YES];
1120- (void) setUpUniverseFromStation
1130 OOSystemID sys = [
self findSystemNumberAtCoords:coords withGalaxy:[player
galaxyNumber] includingHidden:YES];
1135 if (dockedStation && !interstel)
1139 [
self setSystemTo: sys];
1141 while ([entities
count] > 2)
1143 Entity *ent = [entities objectAtIndex:index];
1144 if ((ent != player)&&(ent != dockedStation))
1148 [
self removeEntity:ent];
1158 if (dockedStation ==
nil) [
self removeAllEntitiesExceptPlayer];
1161 if (!dockedStation || !interstel)
1164 [
self populateNormalSpace];
1167 if ([dockedStation maxFlightSpeed] > 0)
1169 float d1 = [
self randomDistanceWithinScanner];
1170 HPVector pos = [UNIVERSE getWitchspaceExitPosition];
1174 if (abs((
int)d1) < 2750)
1176 d1 += ((d1 > 0.0)? 2750.0f: -2750.0f);
1185 [
self setWitchspaceBreakPattern:YES];
1193 if(!autoSaveNow) [
self setViewDirection:VIEW_FORWARD];
1197 [UNIVERSE setSkyColorRed:0.0f
1204- (void) setUpUniverseFromWitchspace
1211 if ([entities
count] == 0)
1216 [
self addEntity:player];
1222 player = [PLAYER retain];
1226 [
self populateNormalSpace];
1231 [
self setViewDirection:VIEW_FORWARD];
1233 [comm_log_gui printLongText:[NSString stringWithFormat:@"%@ %@", [
self getSystemName:systemID], [player
dial_clock_adjusted]]
1240- (void) setUpUniverseFromMisjump
1247 if ([entities
count] == 0)
1252 [
self addEntity:player];
1258 player = [PLAYER retain];
1261 [
self setUpWitchspace];
1264 [
self setAirResistanceFactor:0.0f];
1269 [
self setViewDirection:VIEW_FORWARD];
1275- (void) setUpWitchspace
1277 [
self setUpWitchspaceBetweenSystem:[PLAYER systemID] andSystem:[PLAYER nextHopTargetSystemID]];
1289 NSString* override_key = [
self keyForInterstellarOverridesForSystems:s1 :s2 inGalaxy:galaxyID];
1291 NSDictionary *systeminfo = [systemManager getPropertiesForSystemKey:override_key];
1293 [universeRegion clearSubregions];
1300 thing = [[
SkyEntity alloc] initWithColors:col1:col2 andSystemInfo: systeminfo];
1304 [
self addEntity:thing];
1310 [
self addEntity:thing];
1313 ambientLightLevel = [systeminfo oo_floatForKey:@"ambient_level" defaultValue:1.0];
1319 [
self clearSystemPopulator];
1320 NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:@"interstellarSpaceWillPopulate"];
1321 [system_repopulator release];
1322 system_repopulator = [[systeminfo oo_stringForKey:@"repopulator" defaultValue:@"interstellarSpaceWillRepopulate"] retain];
1324 [PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
1326 [
self populateSystemFromDictionariesWithSun:nil andPlanet:nil];
1329 NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
1330 if (script_actions !=
nil)
1332 OOStandardsDeprecated([NSString stringWithFormat:
@"The script_actions system info key is deprecated for %@.",override_key]);
1351 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1354 NSMutableDictionary *planetDict = [NSMutableDictionary dictionaryWithDictionary:[systemManager getPropertiesForCurrentSystem]];
1355 [planetDict oo_setBool:YES forKey:@"mainForLocalSystem"];
1356 OOPlanetEntity *a_planet = [[
OOPlanetEntity alloc] initFromDictionary:planetDict withAtmosphere:[planetDict oo_boolForKey:@"has_atmosphere" defaultValue:YES] andSeed:systemSeed forSystem:systemID];
1358 double planet_zpos = [planetDict oo_floatForKey:@"planet_distance" defaultValue:500000];
1359 planet_zpos *= [planetDict oo_floatForKey:@"planet_distance_multiplier" defaultValue:1.0];
1361#ifdef OO_DUMP_PLANETINFO
1362 OOLog(
@"planetinfo.record",
@"planet zpos = %f",planet_zpos);
1364 [a_planet
setPosition:(HPVector){ 0, 0, planet_zpos }];
1367 if ([allPlanets
count]>0)
1370 [
self addEntity:a_planet];
1371 [allPlanets removeObject:a_planet];
1372 cachedPlanet=a_planet;
1373 [allPlanets replaceObjectAtIndex:0 withObject:a_planet];
1374 [
self removeEntity:(Entity *)tmp];
1378 [
self addEntity:a_planet];
1380 return [a_planet autorelease];
1394 HPVector stationPos;
1399 NSDictionary *systeminfo = [systemManager getPropertiesForCurrentSystem];
1400 unsigned techlevel = [systeminfo oo_unsignedIntForKey:KEY_TECHLEVEL];
1401 NSString *stationDesc =
nil, *defaultStationDesc =
nil;
1406 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1410 sunGoneNova = [systeminfo oo_boolForKey:@"sun_gone_nova" defaultValue:NO];
1413 [universeRegion clearSubregions];
1416 [
self setSkyColorRed:0.0f
1422#ifdef OO_DUMP_PLANETINFO
1423 OOLog(
@"planetinfo.record",
@"seed = %d %d %d %d",system_seed.c,system_seed.d,system_seed.e,system_seed.f);
1424 OOLog(
@"planetinfo.record",
@"coordinates = %d %d",system_seed.d,system_seed.b);
1426#define SPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = \"%@\";",[systeminfo oo_stringForKey:@"" #PROP]);
1427#define IPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %d;",[systeminfo oo_intForKey:@#PROP]);
1428#define FPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %f;",[systeminfo oo_floatForKey:@"" #PROP]);
1433 IPROP(productivity);
1446 float h2 = h1 + 1.0 / (1.0 + (
Ranrot() % 5));
1452 thing = [[
SkyEntity alloc] initWithColors:col1:col2 andSystemInfo: systeminfo];
1454 [
self addEntity:thing];
1463 ambientLightLevel = [systeminfo oo_floatForKey:@"ambient_level" defaultValue:1.0];
1467 dict_object=[systeminfo objectForKey:@"sun_color"];
1468 if (dict_object!=
nil)
1484 [
self addEntity:thing];
1489 float defaultSunFlare =
randf()*0.1;
1490 float defaultSunHues = 0.5+
randf()*0.5;
1496 a_planet=[
self setUpPlanet];
1497 double planet_radius = [a_planet
radius];
1506 double sun_distance;
1507 double sunDistanceModifier;
1508 double safeDistance;
1511 sunDistanceModifier = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_modifier" defaultValue:0.0];
1512 if (sunDistanceModifier < 6.0)
1514 sun_distance = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance" defaultValue:(planet_radius*20)];
1516 sun_distance *= [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_multiplier" defaultValue:1];
1520 sun_distance = planet_radius * sunDistanceModifier;
1523 sun_radius = [systeminfo oo_nonNegativeDoubleForKey:@"sun_radius" defaultValue:2.5 * planet_radius];
1525 if ((sun_radius < 1000.0) || (sun_radius > sun_distance / 2 && !sunGoneNova))
1527 OOLogWARN(
@"universe.setup.badSun",
@"Sun radius of %f is not valid for this system",sun_radius);
1528 sun_radius = sun_radius < 1000.0 ? 1000.0 : (sun_distance / 2);
1530#ifdef OO_DUMP_PLANETINFO
1531 OOLog(
@"planetinfo.record",
@"sun_radius = %f",sun_radius);
1533 safeDistance=36 * sun_radius * sun_radius;
1537 HPVector sun_dir = [systeminfo oo_hpvectorForKey:@"sun_vector"];
1538 sun_distance /= 2.0;
1541 sun_distance *= 2.0;
1542 sunPos = HPvector_subtract([a_planet position],
1543 HPvector_multiply_scalar(sun_dir,sun_distance));
1547 while (HPmagnitude2(sunPos) < safeDistance);
1551 [a_planet
setOrientation:quaternion_rotation_betweenHP(sun_dir,make_HPvector(1.0,0.0,0.0))];
1553#ifdef OO_DUMP_PLANETINFO
1554 OOLog(
@"planetinfo.record",
@"sun_vector = %.3f %.3f %.3f",vf.x,vf.y,vf.z);
1555 OOLog(
@"planetinfo.record",
@"sun_distance = %.0f",sun_distance);
1560 NSMutableDictionary *sun_dict = [NSMutableDictionary dictionaryWithCapacity:5];
1561 [sun_dict setObject:[NSNumber numberWithDouble:sun_radius] forKey:@"sun_radius"];
1562 dict_object=[systeminfo objectForKey: @"corona_shimmer"];
1563 if (dict_object!=
nil) [sun_dict setObject:dict_object forKey:@"corona_shimmer"];
1564 dict_object=[systeminfo objectForKey: @"corona_hues"];
1565 if (dict_object!=
nil)
1567 [sun_dict setObject:dict_object forKey:@"corona_hues"];
1571 [sun_dict setObject:[NSNumber numberWithFloat:defaultSunHues] forKey:@"corona_hues"];
1573 dict_object=[systeminfo objectForKey: @"corona_flare"];
1574 if (dict_object!=
nil)
1576 [sun_dict setObject:dict_object forKey:@"corona_flare"];
1580 [sun_dict setObject:[NSNumber numberWithFloat:defaultSunFlare] forKey:@"corona_flare"];
1582 dict_object=[systeminfo objectForKey:KEY_SUNNAME];
1583 if (dict_object!=
nil)
1585 [sun_dict setObject:dict_object forKey:KEY_SUNNAME];
1587#ifdef OO_DUMP_PLANETINFO
1588 OOLog(
@"planetinfo.record",
@"corona_flare = %f",[sun_dict oo_floatForKey:
@"corona_flare"]);
1589 OOLog(
@"planetinfo.record",
@"corona_hues = %f",[sun_dict oo_floatForKey:
@"corona_hues"]);
1590 OOLog(
@"planetinfo.record",
@"sun_color = %@",[bgcolor descriptionComponents]);
1592 a_sun = [[
OOSunEntity alloc] initSunWithColor:bgcolor andDictionary:sun_dict];
1597 [
self addEntity:a_sun];
1614 vf = [systeminfo oo_vectorForKey:@"station_vector"];
1615#ifdef OO_DUMP_PLANETINFO
1616 OOLog(
@"planetinfo.record",
@"station_vector = %.3f %.3f %.3f",vf.x,vf.y,vf.z);
1618 stationPos = HPvector_subtract(stationPos, vectorToHPVector(vector_multiply_scalar(vf, 2.0 * planet_radius)));
1622 stationDesc = [systeminfo oo_stringForKey:@"station" defaultValue:@"coriolis"];
1623#ifdef OO_DUMP_PLANETINFO
1624 OOLog(
@"planetinfo.record",
@"station = %@",stationDesc);
1627 a_station = (
StationEntity *)[
self newShipWithRole:stationDesc];
1639 if (![a_station isStation] || ![a_station validForAddToUniverse])
1641 if (a_station ==
nil)
1644 OOLog(
@"universe.setup.badStation",
@"Failed to set up a ship for role \"%@\
" as system station, trying again with \"%@\".", stationDesc, defaultStationDesc);
1648 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);
1650 [a_station release];
1651 stationDesc = defaultStationDesc;
1652 a_station = (
StationEntity *)[
self newShipWithRole:stationDesc];
1654 if (![a_station isStation] || ![a_station validForAddToUniverse])
1656 if (a_station ==
nil)
1658 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);
1662 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);
1664 [a_station release];
1666 a_station = (
StationEntity *)[
self newShipWithName:
@"coriolis-station"];
1667 if (![a_station isStation] || ![a_station validForAddToUniverse])
1669 OOLog(
@"universe.setup.badStation",
@"%@",
@"Could not create built-in Coriolis station! Generating a stationless system.");
1675 if (a_station !=
nil)
1677 [a_station
setOrientation:quaternion_rotation_between(vf,make_vector(0.0,0.0,1.0))];
1683 [
self addEntity:a_station];
1691 cachedPlanet = a_planet;
1692 cachedStation = a_station;
1698 [
self populateSpaceFromActiveWormholes];
1702 [a_station release];
1706- (void) populateNormalSpace
1708 NSDictionary *systeminfo = [systemManager getPropertiesForCurrentSystem];
1710 BOOL sunGoneNova = [systeminfo oo_boolForKey:@"sun_gone_nova"];
1716 HPVector v0 = make_HPvector(0,0,34567.89);
1717 double min_safe_dist2 = 6000000.0 * 6000000.0;
1718 HPVector sunPos = [cachedSun position];
1719 while (HPmagnitude2(cachedSun->position) < min_safe_dist2)
1723 sunPos = HPvector_add(sunPos, v0);
1724 [cachedSun setPosition:sunPos];
1728 [
self removeEntity:cachedPlanet];
1730 [
self removeEntity:cachedStation];
1731 cachedStation =
nil;
1736 [
self clearSystemPopulator];
1738 if ([
PLAYER status] != STATUS_START_GAME)
1740 NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:(sunGoneNova)?@"novaSystemWillPopulate":@"systemWillPopulate"];
1741 [system_repopulator release];
1742 system_repopulator = [[systeminfo oo_stringForKey:@"repopulator" defaultValue:(sunGoneNova)?@"novaSystemWillRepopulate":@"systemWillRepopulate"] retain];
1745 [PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
1747 [
self populateSystemFromDictionariesWithSun:cachedSun andPlanet:cachedPlanet];
1753 NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
1754 if (script_actions !=
nil)
1756 OOStandardsDeprecated([NSString stringWithFormat:
@"The script_actions system info key is deprecated for %@.",[
self getSystemName:systemID]]);
1760 [PLAYER runUnsanitizedScriptActions:script_actions
1761 allowingAIMethods:NO
1762 withContextName:@"<system script_actions>"
1772- (void) clearSystemPopulator
1774 [populatorSettings release];
1775 populatorSettings = [[NSMutableDictionary alloc] initWithCapacity:128];
1779- (NSDictionary *) getPopulatorSettings
1781 return populatorSettings;
1785- (void) setPopulatorSetting:(NSString *)key to:(NSDictionary *)setting
1789 [populatorSettings removeObjectForKey:key];
1793 [populatorSettings setObject:setting forKey:key];
1798- (BOOL) deterministicPopulation
1800 return deterministic_population;
1806 Random_Seed systemSeed = [systemManager getRandomSeedForCurrentSystem];
1807 NSArray *blocks = [populatorSettings allValues];
1808 NSArray *sortedBlocks = [blocks sortedArrayUsingFunction:populatorPrioritySort context:nil];
1809 NSDictionary *populator =
nil;
1811 uint32_t i, locationSeed, groupCount, rndvalue;
1814 NSString *locationCode =
nil;
1816 foreach (populator, sortedBlocks)
1818 deterministic_population = [populator oo_boolForKey:@"deterministic" defaultValue:NO];
1822 deterministic_population = NO;
1825 locationSeed = [populator oo_unsignedIntForKey:@"locationSeed" defaultValue:0];
1826 groupCount = [populator oo_unsignedIntForKey:@"groupCount" defaultValue:1];
1828 for (i = 0; i < groupCount; i++)
1830 locationCode = [populator oo_stringForKey:@"location" defaultValue:@"COORDINATES"];
1831 if ([locationCode isEqualToString:
@"COORDINATES"])
1833 location = [populator oo_hpvectorForKey:@"coordinates" defaultValue:kZeroHPVector];
1837 if (locationSeed != 0)
1853 deterministic_population = NO;
1855 if (sun ==
nil || planet ==
nil)
1858 location = [
self locationByCode:@"WITCHPOINT" withSun:nil andPlanet:nil];
1862 location = [
self locationByCode:locationCode withSun:sun andPlanet:planet];
1864 if(locationSeed != 0)
1871 pdef = [populator objectForKey:@"callbackObj"];
1876 deterministic_population = NO;
1897 if ([code isEqualToString:
@"WITCHPOINT"] || sun ==
nil || planet ==
nil || [sun goneNova])
1904 if ([code isEqualToString:
@"LANE_WPS"])
1907 double l1 = HPmagnitude([planet position]);
1908 double l2 = HPmagnitude(HPvector_subtract([sun position],[planet position]));
1909 double l3 = HPmagnitude([sun position]);
1910 double total = l1+l2+l3;
1911 float choice =
randf();
1912 if (choice < l1/total)
1914 return [
self locationByCode:@"LANE_WP" withSun:sun andPlanet:planet];
1916 else if (choice < (l1+l2)/total)
1918 return [
self locationByCode:@"LANE_PS" withSun:sun andPlanet:planet];
1922 return [
self locationByCode:@"LANE_WS" withSun:sun andPlanet:planet];
1925 else if ([code isEqualToString:
@"LANE_WP"])
1929 else if ([code isEqualToString:
@"LANE_WS"])
1933 else if ([code isEqualToString:
@"LANE_PS"])
1937 else if ([code isEqualToString:
@"STATION_AEGIS"])
1942 }
while(HPdistance2(result,[planet position])<[planet radius]*[planet radius]*1.5);
1945 else if ([code isEqualToString:
@"PLANET_ORBIT_LOW"])
1949 else if ([code isEqualToString:
@"PLANET_ORBIT"])
1953 else if ([code isEqualToString:
@"PLANET_ORBIT_HIGH"])
1957 else if ([code isEqualToString:
@"STAR_ORBIT_LOW"])
1961 else if ([code isEqualToString:
@"STAR_ORBIT"])
1965 else if ([code isEqualToString:
@"STAR_ORBIT_HIGH"])
1969 else if ([code isEqualToString:
@"TRIANGLE"])
1982 result = HPvector_add(HPvector_multiply_scalar([planet position],r),HPvector_multiply_scalar([sun position],s));
1985 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);
1987 else if ([code isEqualToString:
@"INNER_SYSTEM"])
1990 result =
OORandomPositionInShell([sun position],[sun radius]*3.0,HPdistance([sun position],[planet position]));
1994 }
while (HPdistance2(result,[sun position]) < [sun radius]*[sun radius]*9.0);
1996 else if ([code isEqualToString:
@"INNER_SYSTEM_OFFPLANE"])
1998 result =
OORandomPositionInShell([sun position],[sun radius]*3.0,HPdistance([sun position],[planet position]));
2000 else if ([code isEqualToString:
@"OUTER_SYSTEM"])
2002 result =
OORandomPositionInShell([sun position],HPdistance([sun position],[planet position]),HPdistance([sun position],[planet position])*10.0);
2006 else if ([code isEqualToString:
@"OUTER_SYSTEM_OFFPLANE"])
2008 result =
OORandomPositionInShell([sun position],HPdistance([sun position],[planet position]),HPdistance([sun position],[planet position])*10.0);
2020- (void) setAmbientLightLevel:(
float)newValue
2022 NSAssert(
UNIVERSE !=
nil,
@"Attempt to set ambient light level with a non yet existent universe.");
2024 ambientLightLevel = OOClamp_0_max_f(newValue, 10.0f);
2029- (float) ambientLightLevel
2031 return ambientLightLevel;
2055 GLfloat sun_pos[] = {0.0, 0.0, 0.0, 1.0};
2056 GLfloat sun_ambient[] = {0.0, 0.0, 0.0, 1.0};
2059 for (i = n_entities - 1; i > 0; i--)
2060 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[SkyEntity class]]))
2061 the_sky = (
SkyEntity*)sortedEntities[i];
2067 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
2068 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
2069 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
2077 stars_ambient[0] = 0.05; stars_ambient[1] = 0.20; stars_ambient[2] = 0.05; stars_ambient[3] = 1.0;
2078 sun_diffuse[0] = 0.85; sun_diffuse[1] = 1.0; sun_diffuse[2] = 0.85; sun_diffuse[3] = 1.0;
2079 sun_specular[0] = 0.95; sun_specular[1] = 1.0; sun_specular[2] = 0.95; sun_specular[3] = 1.0;
2080 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
2081 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
2082 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
2085 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, sun_pos));
2091 [[the_sky skyColor] getRed:&r green:&g blue:&b alpha:&a];
2095 GLfloat ambient_level = [
self ambientLightLevel];
2099 stars_ambient[3] = 1.0;
2107 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
2112- (void) forceLightSwitch
2118- (void) setMainLightPosition: (Vector) sunPos
2120 main_light_position[0] = sunPos.x;
2121 main_light_position[1] = sunPos.y;
2122 main_light_position[2] = sunPos.z;
2123 main_light_position[3] = 1.0;
2127- (
ShipEntity *) addShipWithRole:(NSString *)desc launchPos:(HPVector)launchPos rfactor:(GLfloat)rfactor
2132 launchPos.x += 2 * rfactor * (
randf() - 0.5);
2133 launchPos.y += 2 * rfactor * (
randf() - 0.5);
2134 launchPos.z += 2 * rfactor * (
randf() - 0.5);
2137 ShipEntity *ship = [
self newShipWithRole:desc];
2144 if ([ship hasRole:
@"cargopod"]) [
self fillCargopodWithRandomCargo:ship];
2147 if (![ship crew] && ![ship isUnpiloted])
2148 [ship
setCrew:[NSArray arrayWithObject:
2152 if ([ship scanClass] == CLASS_NOT_SET)
2156 [
self addEntity:ship];
2164- (void) addShipWithRole:(NSString *) desc nearRouteOneAt:(
double) route_fraction
2168 Entity *theStation = [
self station];
2174 HPVector launchPos = OOHPVectorInterpolate([
self getWitchspaceExitPosition], [theStation position], route_fraction);
2176 [
self addShipWithRole:desc launchPos:launchPos rfactor:SCANNER_MAX_RANGE];
2180- (HPVector) coordinatesForPosition:(HPVector) pos withCoordinateSystem:(NSString *) system returningScalar:(GLfloat*) my_scalar
2217 NSString* l_sys = [system lowercaseString];
2218 if ([l_sys length] != 3)
2222 if (the_planet ==
nil || the_sun ==
nil || [l_sys isEqualToString:
@"abs"])
2224 if (my_scalar) *my_scalar = 1.0;
2227 HPVector w_pos = [
self getWitchspaceExitPosition];
2228 HPVector p_pos = the_planet->
position;
2229 HPVector s_pos = the_sun->
position;
2231 const char* c_sys = [l_sys UTF8String];
2232 HPVector p0, p1, p2;
2241 p1 = p_pos; p2 = s_pos;
break;
2243 p1 = s_pos; p2 = p_pos;
break;
2253 p1 = w_pos; p2 = s_pos;
break;
2255 p1 = s_pos; p2 = w_pos;
break;
2265 p1 = w_pos; p2 = p_pos;
break;
2267 p1 = p_pos; p2 = w_pos;
break;
2275 HPVector k = HPvector_normal_or_zbasis(HPvector_subtract(p1, p0));
2276 HPVector v = HPvector_normal_or_xbasis(HPvector_subtract(p2, p0));
2278 HPVector j = HPcross_product(k, v);
2279 HPVector i = HPcross_product(j, k);
2281 GLfloat scale = 1.0;
2285 scale = [the_planet
radius];
2289 scale = [the_sun
radius];
2293 scale = HPmagnitude(HPvector_subtract(p1, p0));
2307 HPVector result = p0;
2308 result.x += scale * (pos.
x * i.
x + pos.
y * j.
x + pos.z * k.
x);
2309 result.y += scale * (pos.
x * i.
y + pos.
y * j.
y + pos.z * k.
y);
2310 result.z += scale * (pos.
x * i.z + pos.
y * j.z + pos.z * k.z);
2316- (NSString *) expressPosition:(HPVector) pos inCoordinateSystem:(NSString *) system
2318 HPVector result = [
self legacyPositionFrom:pos asCoordinateSystem:system];
2319 return [NSString stringWithFormat:@"%@ %.2f %.2f %.2f", system, result.x, result.y, result.z];
2323- (HPVector) legacyPositionFrom:(HPVector) pos asCoordinateSystem:(NSString *) system
2325 NSString* l_sys = [system lowercaseString];
2326 if ([l_sys length] != 3)
2330 if (the_planet ==
nil || the_sun ==
nil || [l_sys isEqualToString:
@"abs"])
2334 HPVector w_pos = [
self getWitchspaceExitPosition];
2335 HPVector p_pos = the_planet->
position;
2336 HPVector s_pos = the_sun->
position;
2338 const char* c_sys = [l_sys UTF8String];
2339 HPVector p0, p1, p2;
2348 p1 = p_pos; p2 = s_pos;
break;
2350 p1 = s_pos; p2 = p_pos;
break;
2360 p1 = w_pos; p2 = s_pos;
break;
2362 p1 = s_pos; p2 = w_pos;
break;
2372 p1 = w_pos; p2 = p_pos;
break;
2374 p1 = p_pos; p2 = w_pos;
break;
2382 HPVector k = HPvector_normal_or_zbasis(HPvector_subtract(p1, p0));
2383 HPVector v = HPvector_normal_or_xbasis(HPvector_subtract(p2, p0));
2385 HPVector j = HPcross_product(k, v);
2386 HPVector i = HPcross_product(j, k);
2388 GLfloat scale = 1.0;
2393 scale = 1.0f / [the_planet
radius];
2398 scale = 1.0f / [the_sun
radius];
2403 scale = 1.0f / HPdistance(p1, p0);
2415 HPVector r_pos = HPvector_subtract(pos, p0);
2416 HPVector result = make_HPvector(scale * (r_pos.x * i.x + r_pos.y * i.y + r_pos.z * i.z),
2417 scale * (r_pos.x * j.x + r_pos.y * j.y + r_pos.z * j.z),
2418 scale * (r_pos.x * k.x + r_pos.y * k.y + r_pos.z * k.z) );
2424- (HPVector) coordinatesFromCoordinateSystemString:(NSString *) system_x_y_z
2427 if ([tokens
count] != 4)
2430 return make_HPvector(0,0,0);
2433 return [
self coordinatesForPosition:make_HPvector([tokens oo_floatAtIndex:1], [tokens oo_floatAtIndex:2], [tokens oo_floatAtIndex:3]) withCoordinateSystem:[tokens oo_stringAtIndex:0] returningScalar:&dummy];
2437- (BOOL) addShipWithRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2440 GLfloat scalar = 1.0;
2441 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2443 GLfloat rfactor = scalar;
2449 return ([
self addShipWithRole:desc launchPos:launchPos rfactor:rfactor] !=
nil);
2453- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc atPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2456 GLfloat scalar = 1.0;
2457 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2458 GLfloat distance_from_center = 0.0;
2459 HPVector v_from_center, ship_pos;
2460 HPVector ship_positions[howMany];
2462 int scale_up_after = 0;
2463 int current_shell = 0;
2464 GLfloat walk_factor = 2.0;
2467 ShipEntity *ship = [
self addShipWithRole:desc launchPos:launchPos rfactor:0.0];
2468 if (ship ==
nil)
return NO;
2474 int limit_count = 8;
2481 v_from_center.x += walk_factor * (
randf() - 0.5);
2482 v_from_center.y += walk_factor * (
randf() - 0.5);
2483 v_from_center.z += walk_factor * (
randf() - 0.5);
2484 }
while ((v_from_center.x == 0.0)&&(v_from_center.y == 0.0)&&(v_from_center.z == 0.0));
2485 v_from_center = HPvector_normal(v_from_center);
2487 ship_pos = make_HPvector( launchPos.x + distance_from_center * v_from_center.x,
2488 launchPos.y + distance_from_center * v_from_center.y,
2489 launchPos.z + distance_from_center * v_from_center.z);
2494 while (safe && (j >= current_shell))
2496 safe = (safe && (HPdistance2(ship_pos, ship_positions[j]) > safe_distance2));
2505 distance_from_center += sqrt(safe_distance2);
2512 [ship setScanClass:scanClass == CLASS_NOT_SET ? CLASS_NEUTRAL : scanClass];
2520 ship_positions[i] = ship_pos;
2522 if (i > scale_up_after)
2525 scale_up_after += 1 + 2 * i;
2526 distance_from_center += sqrt(safe_distance2);
2533- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system
2536 GLfloat scalar = 1.0;
2537 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2538 GLfloat rfactor = scalar;
2543 BoundingBox launch_bbox;
2544 bounding_box_reset_to_vector(&launch_bbox, make_vector(launchPos.x - rfactor, launchPos.y - rfactor, launchPos.z - rfactor));
2545 bounding_box_add_xyz(&launch_bbox, launchPos.x + rfactor, launchPos.y + rfactor, launchPos.z + rfactor);
2547 return [
self addShips: howMany withRole: desc intoBoundingBox: launch_bbox];
2551- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc nearPosition:(HPVector) pos withCoordinateSystem:(NSString *) system withinRadius:(GLfloat) radius
2554 GLfloat scalar = 1.0;
2555 HPVector launchPos = [
self coordinatesForPosition:pos withCoordinateSystem:system returningScalar:&scalar];
2556 GLfloat rfactor = radius;
2559 BoundingBox launch_bbox;
2560 bounding_box_reset_to_vector(&launch_bbox, make_vector(launchPos.x - rfactor, launchPos.y - rfactor, launchPos.z - rfactor));
2561 bounding_box_add_xyz(&launch_bbox, launchPos.x + rfactor, launchPos.y + rfactor, launchPos.z + rfactor);
2563 return [
self addShips: howMany withRole: desc intoBoundingBox: launch_bbox];
2567- (BOOL) addShips:(
int) howMany withRole:(NSString *) desc intoBoundingBox:(BoundingBox) bbox
2574 int h0 = howMany / 2;
2575 int h1 = howMany - h0;
2577 GLfloat lx = bbox.max.x - bbox.min.
x;
2578 GLfloat ly = bbox.max.y - bbox.min.
y;
2579 GLfloat lz = bbox.max.z - bbox.min.z;
2580 BoundingBox bbox0 = bbox;
2581 BoundingBox bbox1 = bbox;
2582 if ((lx > lz)&&(lx > ly))
2584 bbox0.min.x += 0.5 * lx;
2585 bbox1.max.x -= 0.5 * lx;
2591 bbox0.min.y += 0.5 * ly;
2592 bbox1.max.y -= 0.5 * ly;
2596 bbox0.min.z += 0.5 * lz;
2597 bbox1.max.z -= 0.5 * lz;
2601 return ([
self addShips: h0 withRole: desc intoBoundingBox: bbox0] && [
self addShips: h1 withRole: desc intoBoundingBox: bbox1]);
2605 HPVector pos = make_HPvector(bbox.min.x, bbox.min.y, bbox.min.z);
2606 pos.x += 0.5 * (
randf() +
randf()) * (bbox.max.
x - bbox.min.
x);
2607 pos.y += 0.5 * (
randf() +
randf()) * (bbox.max.
y - bbox.min.
y);
2608 pos.z += 0.5 * (
randf() +
randf()) * (bbox.max.z - bbox.min.z);
2610 return ([
self addShipWithRole:desc launchPos:pos rfactor:0.0] !=
nil);
2614- (BOOL) spawnShip:(NSString *) shipdesc
2618 OOStandardsDeprecated([NSString stringWithFormat:
@"'spawn' via legacy script is deprecated as a way of adding ships for %@",shipdesc]);
2621 NSDictionary *shipdict =
nil;
2624 if (shipdict ==
nil)
return NO;
2626 ship = [
self newShipWithName:shipdesc];
2628 if (ship ==
nil)
return NO;
2631 NSDictionary *spawndict = [shipdict oo_dictionaryForKey:@"spawn"];
2632 HPVector pos, rpos, spos;
2633 NSString *positionString =
nil;
2636 positionString = [spawndict oo_stringForKey:@"position"];
2637 if (positionString !=
nil)
2639 if([positionString hasPrefix:
@"abs "] && ([
self planet] !=
nil || [
self sun] !=
nil))
2641 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);
2644 pos = [
self coordinatesFromCoordinateSystemString:positionString];
2650 OOLogERR(
@"universe.spawnShip.error",
@"***** ERROR: failed to find a spawn position for ship %@.", shipdesc);
2655 positionString = [spawndict oo_stringForKey:@"facing_position"];
2656 if (positionString !=
nil)
2658 if([positionString hasPrefix:
@"abs "] && ([
self planet] !=
nil || [
self sun] !=
nil))
2660 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);
2665 rpos = [
self coordinatesFromCoordinateSystemString:positionString];
2666 rpos = HPvector_subtract(rpos, spos);
2670 rpos = HPvector_normal(rpos);
2679 q1 = make_quaternion(0,1,0,0);
2687 [
self addEntity:ship];
2694- (void) witchspaceShipWithPrimaryRole:(NSString *)role
2698 NSDictionary *systeminfo =
nil;
2701 systeminfo = [
self currentSystemData];
2702 government = [systeminfo oo_unsignedCharForKey:KEY_GOVERNMENT];
2704 ship = [
self newShipWithRole:role];
2707 if (ship && [ship hasRole:
@"cargopod"])
2709 [
self fillCargopodWithRandomCargo:ship];
2714 if (([ship scanClass] == CLASS_NO_DRAW)||([ship scanClass] == CLASS_NOT_SET))
2716 if ([role isEqual:
@"trader"])
2719 if ([ship hasRole:
@"sunskim-trader"] &&
randf() < 0.25)
2722 [
self makeSunSkimmer:ship andSetAI:YES];
2729 if (([ship pendingEscortCount] > 0)&&((
Ranrot() % 7) < government))
2732 [ship setPendingEscortCount:(nx > 0) ? nx : 0];
2735 if ([role isEqual:
@"pirate"])
2738 [ship
setBounty: (Ranrot() & 7) + (Ranrot() & 7) + ((randf() < 0.05)? 63 : 23)
withReason:kOOLegalStatusReasonSetup];
2740 if ([ship crew] ==
nil && ![ship isUnpiloted])
2741 [ship
setCrew:[NSArray arrayWithObject:
2754 if (entity ==
nil)
return nil;
2764 ship = [
self addShipWithRole:desc launchPos:spawn_pos rfactor:0.0];
2781 [vis setPosition:pos];
2782 [vis setOrientation:OORandomQuaternion()];
2784 success = [
self addEntity:vis];
2794- (
ShipEntity *) addShipAt:(HPVector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius
2799 if (radius == NSNotFound)
2801 GLfloat scalar = 1.0;
2802 [
self coordinatesForPosition:pos withCoordinateSystem:@"abs" returningScalar:&scalar];
2804 GLfloat rfactor = scalar;
2818 ShipEntity *ship = [
self newShipWithRole:role];
2824 if ([ship hasRole:
@"cargopod"]) [
self fillCargopodWithRandomCargo:ship];
2826 if (scanClass == CLASS_NOT_SET)
2828 scanClass = CLASS_NEUTRAL;
2832 if ([ship crew] ==
nil && ![ship isUnpiloted])
2834 [ship
setCrew:[NSArray arrayWithObject:
2841 BOOL trader = [role isEqualToString:@"trader"];
2851 if (pendingEscortCount > 0)
2853 OOGovernmentID government = [[
self currentSystemData] oo_unsignedCharForKey:KEY_GOVERNMENT];
2854 if ((
Ranrot() % 7) < government)
2856 int nx = pendingEscortCount - 2 * (1 + (
Ranrot() & 3));
2857 [ship setPendingEscortCount:(nx > 0) ? nx : 0];
2865 success = [
self addEntity:ship];
2872 if ([ship hasRole:
@"sunskim-trader"] &&
randf() < 0.25)
2875 [
self makeSunSkimmer:ship andSetAI:YES];
2882 else if ([role isEqual:
@"pirate"])
2884 [ship
setBounty:(Ranrot() & 7) + (Ranrot() & 7) + ((randf() < 0.05)? 63 : 23)
withReason:kOOLegalStatusReasonSetup];
2901- (NSArray *) addShipsAt:(HPVector)pos withRole:(NSString *)role quantity:(
unsigned)count withinRadius:(GLfloat)radius asGroup:(BOOL)isGroup
2905 NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
2916 ship = [
self addShipAt:pos withRole:role withinRadius:radius];
2920 if (isGroup) [ship
setGroup:group];
2921 [ships addObject:ship];
2925 if ([ships
count] == 0)
return nil;
2927 return [[ships copy] autorelease];
2933- (NSArray *) addShipsToRoute:(NSString *)route withRole:(NSString *)role quantity:(
unsigned)count routeFraction:(
double)routeFraction asGroup:(BOOL)isGroup
2935 NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
2941 if ([route isEqualToString:
@"pw"] || [route isEqualToString:
@"sw"] || [route isEqualToString:
@"ps"])
2943 routeFraction = 1.0f - routeFraction;
2947 if ([route isEqualTo:
@"wp"] || [route isEqualTo:
@"pw"])
2949 point0 = [
self getWitchspaceExitPosition];
2950 entity = [
self planet];
2951 if (entity ==
nil)
return nil;
2953 radius = [entity radius];
2955 else if ([route isEqualTo:
@"ws"] || [route isEqualTo:
@"sw"])
2957 point0 = [
self getWitchspaceExitPosition];
2958 entity = [
self sun];
2959 if (entity ==
nil)
return nil;
2961 radius = [entity radius];
2963 else if ([route isEqualTo:
@"sp"] || [route isEqualTo:
@"ps"])
2965 entity = [
self sun];
2966 if (entity ==
nil)
return nil;
2968 double radius0 = [entity radius];
2970 entity = [
self planet];
2971 if (entity ==
nil)
return nil;
2973 radius = [entity radius];
2976 direction = HPvector_normal(HPvector_subtract(point0, point1));
2977 point0 = HPvector_subtract(point0, HPvector_multiply_scalar(direction, radius0 +
SCANNER_MAX_RANGE * 1.1f));
2979 else if ([route isEqualTo:
@"st"])
2981 point0 = [
self getWitchspaceExitPosition];
2982 if ([
self station] ==
nil)
return nil;
2983 point1 = [[
self station] position];
2984 radius = [[
self station] collisionRadius];
2989 direction = HPvector_normal(HPvector_subtract(point1, point0));
2990 point1 = HPvector_subtract(point1, HPvector_multiply_scalar(direction, radius +
SCANNER_MAX_RANGE * 1.1f));
2992 pos = [
self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
2995 return [
self addShipsAt:pos withRole:role quantity:count withinRadius:(SCANNER_MAX_RANGE / 10.0f) asGroup:YES];
3001 ship = [
self addShipAt:pos withRole:role withinRadius:0];
3002 if (ship !=
nil) [ships addObject:ship];
3003 if (
count > 0) pos = [
self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
3006 if ([ships
count] == 0)
return nil;
3009 return [[ships copy] autorelease];
3013- (BOOL) roleIsPirateVictim:(NSString *)role
3015 return [
self role:role isInCategory:@"oolite-pirate-victim"];
3019- (BOOL) role:(NSString *)role isInCategory:(NSString *)category
3021 NSSet *categoryInfo = [roleCategories objectForKey:category];
3022 if (categoryInfo ==
nil)
3026 return [categoryInfo containsObject:role];
3031- (void) forceWitchspaceEntries
3034 for (i = 0; i < n_entities; i++)
3036 if (sortedEntities[i]->isShip)
3040 if ([my_target isWormhole])
3044 else if ([[[my_ship getAI] state] isEqualToString:
@"ENTER_WORMHOLE"])
3053- (void) addWitchspaceJumpEffectForShip:(
ShipEntity *)ship
3056 if ([
PLAYER status] != STATUS_ENTERING_WITCHSPACE && [
PLAYER status] != STATUS_EXITING_WITCHSPACE)
3064- (GLfloat) safeWitchspaceExitDistance
3066 for (
unsigned i = 0; i < n_entities; i++)
3068 Entity *e2 = sortedEntities[i];
3069 if ([e2 isShip] && [(
ShipEntity*)e2 hasPrimaryRole:
@"buoy-witchpoint"])
3078- (void) setUpBreakPattern:(HPVector) pos orientation:(Quaternion) q forDocking:(BOOL) forDocking
3085 [
self setViewDirection:VIEW_FORWARD];
3097 colorDesc = [[
self globalSettings] objectForKey:@"hyperspace_tunnel_color_1"];
3098 if (colorDesc !=
nil)
3101 if (color !=
nil) col1 = color;
3102 else OOLogWARN(
@"hyperspaceTunnel.fromDict",
@"could not interpret \"%@\
" as a colour.", colorDesc);
3105 colorDesc = [[
self globalSettings] objectForKey:@"hyperspace_tunnel_color_2"];
3106 if (colorDesc !=
nil)
3109 if (color !=
nil) col2 = color;
3110 else OOLogWARN(
@"hyperspaceTunnel.fromDict",
@"could not interpret \"%@\
" as a colour.", colorDesc);
3114 GLfloat startAngle = 0;
3115 GLfloat aspectRatio = 1;
3119 NSDictionary *info = [[PLAYER dockedStation] shipInfoDictionary];
3120 sides = [info oo_unsignedIntForKey:@"tunnel_corners" defaultValue:4];
3121 startAngle = [info oo_floatForKey:@"tunnel_start_angle" defaultValue:45.0f];
3122 aspectRatio = [info oo_floatForKey:@"tunnel_aspect_ratio" defaultValue:2.67f];
3125 for (i = 1; i < 11; i++)
3134 [ring
setPosition:HPvector_add(pos, vectorToHPVector(offset))];
3137 [ring
setLifetime:i * BREAK_PATTERN_RING_SPACING];
3141 if (forDocking && ![[
PLAYER dockedStation] hasBreakPattern])
3145 else if (!forDocking && ![
self witchspaceBreakPattern])
3149 [
self addEntity:ring];
3150 breakPatternCounter++;
3155- (BOOL) witchspaceBreakPattern
3157 return _witchspaceBreakPattern;
3161- (void) setWitchspaceBreakPattern:(BOOL)newValue
3163 _witchspaceBreakPattern = !!newValue;
3167- (BOOL) dockingClearanceProtocolActive
3169 return _dockingClearanceProtocolActive;
3173- (void) setDockingClearanceProtocolActive:(BOOL)newValue
3183 foreach (station, allStations)
3186 if (![[[registry shipInfoForKey:stationKey] allKeys] containsObject:
@"requires_docking_clearance"])
3192 _dockingClearanceProtocolActive = !!newValue;
3196- (void) handleGameOver
3198 if ([[
self gameController] playerFileToLoad])
3200 [[
self gameController] loadPlayerIfRequired];
3204 [
self setUseAddOns:SCENARIO_OXP_DEFINITION_ALL fromSaveGame:NO forceReinit:YES];
3209- (void) setupIntroFirstGo:(BOOL)justCobra
3213 Quaternion q2 = { 0.0f, 0.0f, 1.0f, 0.0f };
3221 [
self removeDemoShips];
3233 ship = [
self newShipWithName:PLAYER_SHIP_DESC usePlayerProxy:YES];
3239 demo_ship_index = 0;
3240 demo_ship_subindex = 0;
3244 NSArray *subList =
nil;
3245 foreach (subList, demo_ships)
3247 if ([[[subList oo_dictionaryAtIndex:0] oo_stringForKey:
kOODemoShipClass] isEqualToString:
@"ship"])
3249 demo_ship_index = [demo_ships indexOfObject:subList];
3250 NSDictionary *shipEntry =
nil;
3251 foreach (shipEntry, subList)
3253 if ([[shipEntry oo_stringForKey:
kOODemoShipKey] isEqualToString:
@"cobra3-trader"])
3255 demo_ship_subindex = [subList indexOfObject:shipEntry];
3264 if (!demo_ship) ship = [
self newShipWithName:[[[demo_ships oo_arrayAtIndex:demo_ship_index] oo_dictionaryAtIndex:demo_ship_subindex] oo_stringForKey:kOODemoShipKey] usePlayerProxy:NO];
3275 [ship
setPositionX:0.0f
y:0.0f
z:DEMO2_VANISHING_DISTANCE * ship->collision_radius * 0.01];
3288 [
self addEntity:ship];
3290 [ship
setStatus:STATUS_COCKPIT_DISPLAY];
3299 [
self setLibraryTextForDemoShip];
3302 [
self enterGUIViewModeWithMouseInteraction:NO];
3306 demo_stage_time = universal_time + 300.0;
3313 return [[demo_ships oo_arrayAtIndex:demo_ship_index] oo_dictionaryAtIndex:demo_ship_subindex];
3323 [gui setTabStops:tab_stops];
3328 NSDictionary *librarySettings = [
self demoShipData];
3332 NSString *field1 =
nil;
3333 NSString *field2 =
nil;
3334 NSString *field3 =
nil;
3335 NSString *
override =
nil;
3338 for (NSUInteger i=1;i<=26;i++)
3340 [gui setText:@"" forRow:i];
3344 override = [librarySettings oo_stringForKey:kOODemoShipClass defaultValue:@"ship"];
3348 field2 = [demo_ship shipClassName];
3351 override = [librarySettings oo_stringForKey:kOODemoShipSummary defaultValue:nil];
3352 if (
override !=
nil)
3360 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:1];
3372 override = [librarySettings oo_stringForKey:kOODemoShipSpeed defaultValue:nil];
3373 if (
override !=
nil)
3375 if ([
override length] == 0)
3381 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-speed-custom"),OOExpand(override)];
3390 override = [librarySettings oo_stringForKey:kOODemoShipTurnRate defaultValue:nil];
3391 if (
override !=
nil)
3393 if ([
override length] == 0)
3399 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-turn-custom"),OOExpand(override)];
3408 override = [librarySettings oo_stringForKey:kOODemoShipCargo defaultValue:nil];
3409 if (
override !=
nil)
3411 if ([
override length] == 0)
3417 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-cargo-custom"),OOExpand(override)];
3426 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:3];
3429 override = [librarySettings oo_stringForKey:kOODemoShipGenerator defaultValue:nil];
3430 if (
override !=
nil)
3432 if ([
override length] == 0)
3438 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-generator-custom"),OOExpand(override)];
3447 override = [librarySettings oo_stringForKey:kOODemoShipShields defaultValue:nil];
3448 if (
override !=
nil)
3450 if ([
override length] == 0)
3456 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-shields-custom"),OOExpand(override)];
3465 override = [librarySettings oo_stringForKey:kOODemoShipWitchspace defaultValue:nil];
3466 if (
override !=
nil)
3468 if ([
override length] == 0)
3474 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-witchspace-custom"),OOExpand(override)];
3483 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:4];
3487 override = [librarySettings oo_stringForKey:kOODemoShipWeapons defaultValue:nil];
3488 if (
override !=
nil)
3490 if ([
override length] == 0)
3496 field1 = [NSString stringWithFormat:DESC(@"oolite-ship-library-weapons-custom"),OOExpand(override)];
3504 override = [librarySettings oo_stringForKey:kOODemoShipTurrets defaultValue:nil];
3505 if (
override !=
nil)
3507 if ([
override length] == 0)
3513 field2 = [NSString stringWithFormat:DESC(@"oolite-ship-library-turrets-custom"),OOExpand(override)];
3521 override = [librarySettings oo_stringForKey:kOODemoShipSize defaultValue:nil];
3522 if (
override !=
nil)
3524 if ([
override length] == 0)
3530 field3 = [NSString stringWithFormat:DESC(@"oolite-ship-library-size-custom"),OOExpand(override)];
3538 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:5];
3541 override = [librarySettings oo_stringForKey:kOODemoShipDescription defaultValue:nil];
3542 if (
override !=
nil)
3544 [gui addLongText:OOExpand(override) startingAtRow:descRow align:GUI_ALIGN_LEFT];
3549 field1 = [NSString stringWithFormat:@"<-- %@",OOShipLibraryCategoryPlural([[[demo_ships objectAtIndex:((demo_ship_index+[demo_ships count]-1)%[demo_ships count])] objectAtIndex:0] oo_stringForKey:kOODemoShipClass])];
3551 field3 = [NSString stringWithFormat:@"%@ -->",OOShipLibraryCategoryPlural([[[demo_ships objectAtIndex:((demo_ship_index+1)%[demo_ships count])] objectAtIndex:0] oo_stringForKey:kOODemoShipClass])];
3553 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:19];
3557 NSArray *subList = [demo_ships objectAtIndex:demo_ship_index];
3558 NSUInteger i,start = demo_ship_subindex - (demo_ship_subindex%5);
3559 NSUInteger end = start + 4;
3560 if (end >= [subList
count])
3562 end = [subList count] - 1;
3567 for (i = start ; i <= end ; i++)
3569 field2 = [[subList objectAtIndex:i] oo_stringForKey:kOODemoShipName];
3570 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:row];
3571 if (i == demo_ship_subindex)
3585 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:20];
3588 if (end < [subList
count]-1)
3590 [gui setArray:[NSArray arrayWithObjects:field1,field2,field3,nil] forRow:26];
3597- (void) selectIntro2Previous
3600 NSUInteger subcount = [[demo_ships objectAtIndex:demo_ship_index] count];
3601 demo_ship_subindex = (demo_ship_subindex + subcount - 2) % subcount;
3602 demo_stage_time = universal_time - 1.0;
3606- (void) selectIntro2PreviousCategory
3609 demo_ship_index = (demo_ship_index + [demo_ships
count] - 1) % [demo_ships
count];
3610 demo_ship_subindex = [[demo_ships objectAtIndex:demo_ship_index] count] - 1;
3611 demo_stage_time = universal_time - 1.0;
3615- (void) selectIntro2NextCategory
3618 demo_ship_index = (demo_ship_index + 1) % [demo_ships
count];
3619 demo_ship_subindex = [[demo_ships objectAtIndex:demo_ship_index] count] - 1;
3620 demo_stage_time = universal_time - 1.0;
3624- (void) selectIntro2Next
3627 demo_stage_time = universal_time - 1.0;
3637static BOOL IsFriendlyStationPredicate(
Entity *entity,
void *parameter)
3645 if (cachedSun !=
nil && cachedStation ==
nil)
3647 cachedStation = [
self findOneEntityMatchingPredicate:IsCandidateMainStationPredicate
3650 return cachedStation;
3654- (
StationEntity *) stationWithRole:(NSString *)role andPosition:(HPVector)position
3656 if ([role isEqualToString:
@""])
3661 float range = 1000000;
3663 NSArray *stations = [
self stations];
3665 foreach (station, stations)
3667 if (HPdistance2(position,[station position]) < range)
3669 if ([[station primaryRole] isEqualToString:role])
3683 return [
self findOneEntityMatchingPredicate:IsFriendlyStationPredicate parameter:ship];
3689 if (cachedPlanet ==
nil && [allPlanets
count] > 0)
3691 cachedPlanet = [allPlanets objectAtIndex:0];
3693 return cachedPlanet;
3699 if (cachedSun ==
nil)
3701 cachedSun = [
self findOneEntityMatchingPredicate:IsSunPredicate parameter:nil];
3707- (NSArray *) planets
3713- (NSArray *) stations
3715 return [allStations allObjects];
3719- (NSArray *) wormholes
3721 return activeWormholes;
3725- (void) unMagicMainStation
3737 if (playerStatus == STATUS_START_GAME)
return;
3741 cachedStation =
nil;
3745- (void) resetBeacons
3747 Entity <OOBeaconEntity> *beaconShip = [
self firstBeacon], *next =
nil;
3750 next = [beaconShip nextBeacon];
3751 [beaconShip setPrevBeacon:nil];
3752 [beaconShip setNextBeacon:nil];
3756 [
self setFirstBeacon:nil];
3757 [
self setLastBeacon:nil];
3761- (
Entity <OOBeaconEntity> *) firstBeacon
3763 return [_firstBeacon weakRefUnderlyingObject];
3767- (void) setFirstBeacon:(
Entity <OOBeaconEntity> *)beacon
3769 if (beacon != [
self firstBeacon])
3771 [beacon setPrevBeacon:nil];
3772 [beacon setNextBeacon:[
self firstBeacon]];
3773 [[
self firstBeacon] setPrevBeacon:beacon];
3774 [_firstBeacon release];
3775 _firstBeacon = [beacon weakRetain];
3780- (
Entity <OOBeaconEntity> *) lastBeacon
3782 return [_lastBeacon weakRefUnderlyingObject];
3786- (void) setLastBeacon:(
Entity <OOBeaconEntity> *)beacon
3788 if (beacon != [
self lastBeacon])
3790 [beacon setNextBeacon:nil];
3791 [beacon setPrevBeacon:[
self lastBeacon]];
3792 [[
self lastBeacon] setNextBeacon:beacon];
3793 [_lastBeacon release];
3794 _lastBeacon = [beacon weakRetain];
3799- (void) setNextBeacon:(
Entity <OOBeaconEntity> *) beaconShip
3801 if ([beaconShip isBeacon])
3803 [
self setLastBeacon:beaconShip];
3804 if ([
self firstBeacon] ==
nil) [
self setFirstBeacon:beaconShip];
3808 OOLog(
@"universe.beacon.error",
@"***** ERROR: Universe setNextBeacon '%@'. The ship has no beacon code set.", beaconShip);
3813- (void) clearBeacon:(
Entity <OOBeaconEntity> *) beaconShip
3815 Entity <OOBeaconEntity> *tmp =
nil;
3817 if ([beaconShip isBeacon])
3819 if ([
self firstBeacon] == beaconShip)
3821 tmp = [[beaconShip nextBeacon] nextBeacon];
3822 [
self setFirstBeacon:[beaconShip nextBeacon]];
3823 [[beaconShip prevBeacon] setNextBeacon:tmp];
3825 else if ([
self lastBeacon] == beaconShip)
3827 tmp = [[beaconShip prevBeacon] prevBeacon];
3828 [
self setLastBeacon:[beaconShip prevBeacon]];
3829 [[beaconShip nextBeacon] setPrevBeacon:tmp];
3833 [[beaconShip nextBeacon] setPrevBeacon:[beaconShip prevBeacon]];
3834 [[beaconShip prevBeacon] setNextBeacon:[beaconShip nextBeacon]];
3836 [beaconShip setBeaconCode:nil];
3841- (NSDictionary *) currentWaypoints
3847- (void) defineWaypoint:(NSDictionary *)definition forKey:(NSString *)key
3850 BOOL preserveCompass = NO;
3851 waypoint = [waypoints objectForKey:key];
3852 if (waypoint !=
nil)
3854 if ([
PLAYER compassTarget] == waypoint)
3856 preserveCompass = YES;
3858 [
self removeEntity:waypoint];
3859 [waypoints removeObjectForKey:key];
3861 if (definition !=
nil)
3864 if (waypoint !=
nil)
3866 [
self addEntity:waypoint];
3867 [waypoints setObject:waypoint forKey:key];
3868 if (preserveCompass)
3870 [PLAYER setCompassTarget:waypoint];
3871 [PLAYER setNextBeacon:waypoint];
3878- (GLfloat *) skyClearColor
3880 return skyClearColor;
3884- (void) setSkyColorRed:(GLfloat)red green:(GLfloat)green blue:(GLfloat)blue alpha:(GLfloat)alpha
3886 skyClearColor[0] = red;
3887 skyClearColor[1] = green;
3888 skyClearColor[2] = blue;
3889 skyClearColor[3] = alpha;
3890 [
self setAirResistanceFactor:alpha];
3894- (BOOL) breakPatternOver
3896 return (breakPatternCounter == 0);
3900- (BOOL) breakPatternHide
3903 return ((breakPatternCounter > 5)||(!player)||([player status] == STATUS_DOCKING));
3907#define PROFILE_SHIP_SELECTION 0
3910- (BOOL) canInstantiateShip:(NSString *)shipKey
3912 NSDictionary *shipInfo =
nil;
3913 NSArray *conditions =
nil;
3914 NSString *condition_script =
nil;
3917 condition_script = [shipInfo oo_stringForKey:@"condition_script"];
3918 if (condition_script !=
nil)
3920 OOJSScript *condScript = [
self getConditionScript:condition_script];
3921 if (condScript !=
nil)
3925 JSBool allow_instantiation;
3929 OK = [condScript
callMethod:OOJSID("allowSpawnShip")
3934 if (OK) OK = JS_ValueToBoolean(context, result, &allow_instantiation);
3938 if (OK && !allow_instantiation)
3948 conditions = [shipInfo oo_arrayForKey:@"conditions"];
3949 if (conditions ==
nil)
return YES;
3952 return [PLAYER scriptTestConditions:conditions];
3956- (NSString *) randomShipKeyForRoleRespectingConditions:(NSString *)role
3961 NSString *shipKey =
nil;
3964#if PROFILE_SHIP_SELECTION
3965 static unsigned long profTotal = 0, profSlowPath = 0;
3970 shipKey = [registry randomShipKeyForRole:role];
3971 if ([
self canInstantiateShip:shipKey]) return shipKey;
3980#if PROFILE_SHIP_SELECTION
3982 if ((profSlowPath % 10) == 0)
3984 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);
3988 pset = [[[registry probabilitySetForRole:role] mutableCopy] autorelease];
3990 while ([pset
count] > 0)
3994 if ([
self canInstantiateShip:shipKey]) return shipKey;
4007- (
ShipEntity *) newShipWithRole:(NSString *)role
4012 NSString *shipKey =
nil;
4013 NSDictionary *shipInfo =
nil;
4014 NSString *autoAI =
nil;
4016 shipKey = [
self randomShipKeyForRoleRespectingConditions:role];
4019 ship = [
self newShipWithName:shipKey];
4022 [ship setPrimaryRole:role];
4025 if ([shipInfo oo_fuzzyBooleanForKey:
@"auto_ai" defaultValue:YES])
4028 autoAI = [
self defaultAIForRole:role];
4031 [ship setAITo:autoAI];
4034 if ([role isEqualToString:
@"pirate"]) [ship setBounty:20 +
randf() * 50 withReason:kOOLegalStatusReasonSetup];
4035 if ([role isEqualToString:
@"trader"]) [ship setBounty:0 withReason:kOOLegalStatusReasonSetup];
4036 if ([role isEqualToString:
@"police"]) [ship setScanClass:CLASS_POLICE];
4037 if ([role isEqualToString:
@"interceptor"])
4039 [ship setScanClass: CLASS_POLICE];
4040 [ship setPrimaryRole:@"police"];
4043 if ([role isEqualToString:
@"thargoid"]) [ship setScanClass: CLASS_THARGOID];
4058 NSDictionary *effectDict =
nil;
4062 if (effectDict ==
nil)
return nil;
4068 @catch (NSException *exception)
4072 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newVisualEffectWithName: %@ ] *****", [exception reason], effectKey);
4074 else @throw exception;
4083- (
ShipEntity *) newSubentityWithName:(NSString *)shipKey andScaleFactor:(
float)scale
4085 return [
self newShipWithName:shipKey usePlayerProxy:NO isSubentity:YES andScaleFactor:scale];
4089- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy
4091 return [
self newShipWithName:shipKey usePlayerProxy:usePlayerProxy isSubentity:NO];
4094- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy isSubentity:(BOOL)isSubentity
4096 return [
self newShipWithName:shipKey usePlayerProxy:usePlayerProxy isSubentity:isSubentity andScaleFactor:1.0f];
4099- (
ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy isSubentity:(BOOL)isSubentity andScaleFactor:(
float)scale
4103 NSDictionary *shipDict =
nil;
4107 if (shipDict ==
nil)
return nil;
4109 volatile Class shipClass =
nil;
4116 shipClass = [
self shipClassForShipDictionary:shipDict];
4117 if (usePlayerProxy && shipClass == [
ShipEntity class])
4127 NSMutableDictionary *mShipDict = [shipDict mutableCopy];
4128 [mShipDict setObject:[NSNumber numberWithFloat:scale] forKey:@"model_scale_factor"];
4129 shipDict = [NSDictionary dictionaryWithDictionary:mShipDict];
4130 [mShipDict release];
4132 ship = [[shipClass alloc] initWithKey:shipKey definition:shipDict];
4134 @catch (NSException *exception)
4138 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newShipWithName: %@ ] *****", [exception reason], shipKey);
4140 else @throw exception;
4145 if ([ship hasRole:shipKey]) [ship setPrimaryRole:shipKey];
4153- (
DockEntity *) newDockWithName:(NSString *)shipDataKey andScaleFactor:(
float)scale
4157 NSDictionary *shipDict =
nil;
4161 if (shipDict ==
nil)
return nil;
4167 NSMutableDictionary *mShipDict = [shipDict mutableCopy];
4168 [mShipDict setObject:[NSNumber numberWithFloat:scale] forKey:@"model_scale_factor"];
4169 shipDict = [NSDictionary dictionaryWithDictionary:mShipDict];
4170 [mShipDict release];
4172 dock = [[
DockEntity alloc] initWithKey:shipDataKey definition:shipDict];
4174 @catch (NSException *exception)
4178 OOLog(
kOOLogException,
@"***** Oolite Exception : '%@' in [Universe newDockWithName: %@ ] *****", [exception reason], shipDataKey);
4180 else @throw exception;
4185 if ([dock hasRole:shipDataKey]) [dock setPrimaryRole:shipDataKey];
4193- (
ShipEntity *) newShipWithName:(NSString *)shipKey
4195 return [
self newShipWithName:shipKey usePlayerProxy:NO];
4199- (Class) shipClassForShipDictionary:(NSDictionary *)dict
4203 if (dict ==
nil)
return Nil;
4205 BOOL isStation = NO;
4206 NSString *shipRoles = [dict oo_stringForKey:@"roles"];
4208 if (shipRoles !=
nil)
4210 isStation = [shipRoles rangeOfString:@"station"].location != NSNotFound ||
4211 [shipRoles rangeOfString:@"carrier"].location != NSNotFound;
4215 isStation = [dict oo_boolForKey:@"isCarrier" defaultValue:isStation];
4216 isStation = [dict oo_boolForKey:@"is_carrier" defaultValue:isStation];
4225- (NSString *)defaultAIForRole:(NSString *)role
4227 return [autoAIMap oo_stringForKey:role];
4242 foreach (itemData, equipmentData)
4244 NSString *itemType = [itemData oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
4246 if ([itemType isEqual:eq_key])
4248 return [itemData oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
4264 if ([cargoObj isTemplateCargoPod])
4266 return [UNIVERSE cargoPodFromTemplate:cargoObj];
4280 OOCargoQuantity co_amount = [UNIVERSE getRandomAmountOfCommodity:co_type];
4283 container = [UNIVERSE newShipWithRole:co_type];
4285 if (container ==
nil)
4287 container = [UNIVERSE newShipWithRole:@"cargopod"];
4290 return [container autorelease];
4294- (NSArray *) getContainersOfGoods:(
OOCargoQuantity)how_many scarce:(BOOL)scarce legal:(BOOL)legal
4300 NSMutableArray *accumulator = [NSMutableArray arrayWithCapacity:how_many];
4301 NSUInteger i=0, commodityCount = [commodityMarket count];
4305 NSArray *goodsKeys = [commodityMarket goods];
4306 NSString *goodsKey =
nil;
4308 foreach (goodsKey, goodsKeys)
4313 if (q < 64) q = 64 - q;
4318 if (legal && [commodityMarket exportLegalityForGood:goodsKey] > 0)
4324 quantities[i++] = q;
4325 total_quantity += q;
4328 for (i = 0; i < how_many; i++)
4330 NSUInteger co_type = 0;
4335 qr = 1+(
Ranrot() % total_quantity);
4339 NSAssert((NSUInteger)co_type < commodityCount,
@"Commodity type index out of range.");
4340 qr -= quantities[co_type++];
4345 ShipEntity *container = [cargoPods objectForKey:[goodsKeys oo_stringAtIndex:co_type]];
4347 if (container !=
nil)
4349 [accumulator addObject:container];
4353 OOLog(
@"universe.createContainer.failed",
@"***** ERROR: failed to find a container to fill with %@ (%llu).", [goodsKeys oo_stringAtIndex:co_type], co_type);
4357 return [NSArray arrayWithArray:accumulator];
4363 NSMutableArray *accumulator = [NSMutableArray arrayWithCapacity:how_much];
4364 if (![commodities goodDefined:commodity_name])
4366 return [NSArray array];
4369 ShipEntity *container = [cargoPods objectForKey:commodity_name];
4370 while (how_much > 0)
4374 [accumulator addObject:container];
4378 OOLog(
@"universe.createContainer.failed",
@"***** ERROR: failed to find a container to fill with %@", commodity_name);
4383 return [NSArray arrayWithArray:accumulator];
4387- (void) fillCargopodWithRandomCargo:(
ShipEntity *)cargopod
4389 if (cargopod ==
nil || ![cargopod hasRole:
@"cargopod"] || [cargopod cargoType] ==
CARGO_SCRIPTED_ITEM) return;
4391 if ([cargopod commodityType] ==
nil || ![cargopod commodityAmount])
4393 NSString *aCommodity = [
self getRandomCommodity];
4394 OOCargoQuantity aQuantity = [
self getRandomAmountOfCommodity:aCommodity];
4400- (NSString *) getRandomCommodity
4402 return [commodities getRandomCommodity];
4410 if (co_type ==
nil) {
4414 units = [commodities massUnitForGood:co_type];
4424 OOLog(
@"universe.commodityAmount.warning",
@"Commodity %@ has an unrecognised mass unit, assuming tonnes",co_type);
4431 return [commodityMarket definitionForGood:type];
4437 return [commodityMarket nameForGood:co_type];
4444 NSString *unitDesc =
nil, *typeDesc =
nil;
4445 NSDictionary *commodity = [
self commodityDataForType:co_type];
4447 if (commodity ==
nil)
return @"";
4449 units = [commodityMarket massUnitForGood:co_type];
4455 unitDesc =
DESC(
@"cargo-kilogram");
4458 unitDesc =
DESC(
@"cargo-gram");
4462 unitDesc =
DESC(
@"cargo-ton");
4471 unitDesc =
DESC(
@"cargo-kilograms");
4474 unitDesc =
DESC(
@"cargo-grams");
4478 unitDesc =
DESC(
@"cargo-tons");
4483 typeDesc = [commodityMarket nameForGood:co_type];
4485 return [NSString stringWithFormat:@"%d %@ %@",co_amount, unitDesc, typeDesc];
4493 gameView = [view retain];
4505 return [[
self gameView] gameController];
4509- (NSDictionary *) gameSettings
4512 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:12];
4514 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:10];
4517 [result oo_setInteger:[PLAYER isSpeechOn] forKey:@"speechOn"];
4518 [result oo_setBool:autoSave forKey:@"autosave"];
4519 [result oo_setBool:wireframeGraphics forKey:@"wireframeGraphics"];
4520 [result oo_setBool:doProcedurallyTexturedPlanets forKey:@"procedurallyTexturedPlanets"];
4522 [result oo_setFloat:[gameView fov:NO] forKey:@"fovValue"];
4525 if ([gameView hdrOutput])
4527 [result oo_setFloat:[gameView hdrMaxBrightness] forKey:@"hdr-max-brightness"];
4528 [result oo_setFloat:[gameView hdrPaperWhiteBrightness] forKey:@"hdr-paperwhite-brightness"];
4529 [result setObject:OOStringFromHDRToneMapper([gameView hdrToneMapper]) forKey:@"hdr-tone-mapper"];
4533 [result setObject:OOStringFromSDRToneMapper([gameView sdrToneMapper]) forKey:@"sdr-tone-mapper"];
4535 [result setObject:OOStringFromGraphicsDetail([
self detailLevel]) forKey:@"detailLevel"];
4537 NSString *desc =
@"UNDEFINED";
4544 [result setObject:desc forKey:@"musicMode"];
4546 NSDictionary *gameWindow = [NSDictionary dictionaryWithObjectsAndKeys:
4547 [NSNumber numberWithFloat:[gameView backingViewSize].width], @"width",
4548 [NSNumber numberWithFloat:[gameView backingViewSize].height], @"height",
4549 [NSNumber numberWithBool:[[
self gameController] inFullScreenMode]], @"fullScreen",
4551 [result setObject:gameWindow forKey:@"gameWindow"];
4553 [result setObject:[PLAYER keyConfig] forKey:@"keyConfig"];
4555 return [[result copy] autorelease];
4559- (void) useGUILightSource:(BOOL)GUILight
4563 if (![
self useShaders])
4567 OOGL(glEnable(GL_LIGHT0));
4568 OOGL(glDisable(GL_LIGHT1));
4572 OOGL(glEnable(GL_LIGHT1));
4573 OOGL(glDisable(GL_LIGHT0));
4582 else OOGL(glEnable(GL_LIGHT1));
4589- (void) lightForEntity:(BOOL)isLit
4593 if ([
self useShaders])
4597 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
4598 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
4610 if (isLit)
OOGL(glEnable(GL_LIGHT1));
4611 else OOGL(glDisable(GL_LIGHT1));
4616 OOGL(glEnable(GL_LIGHT0));
4632 { 1.0f, 0.0f, 0.0f, 0.0f },
4633 { 0.0f, 1.0f, 0.0f, 0.0f },
4634 { 0.0f, 0.0f, 1.0f, 0.0f },
4635 { 0.0f, 0.0f, 0.0f, 1.0f }
4639 {-1.0f, 0.0f, 0.0f, 0.0f },
4640 { 0.0f, 1.0f, 0.0f, 0.0f },
4641 { 0.0f, 0.0f, -1.0f, 0.0f },
4642 { 0.0f, 0.0f, 0.0f, 1.0f }
4646 { 0.0f, 0.0f, -1.0f, 0.0f },
4647 { 0.0f, 1.0f, 0.0f, 0.0f },
4648 { 1.0f, 0.0f, 0.0f, 0.0f },
4649 { 0.0f, 0.0f, 0.0f, 1.0f }
4653 { 0.0f, 0.0f, 1.0f, 0.0f },
4654 { 0.0f, 1.0f, 0.0f, 0.0f },
4655 {-1.0f, 0.0f, 0.0f, 0.0f },
4656 { 0.0f, 0.0f, 0.0f, 1.0f }
4660- (void) getActiveViewMatrix:(OOMatrix *)outMatrix forwardVector:(Vector *)outForward upVector:(Vector *)outUp
4662 assert(outMatrix != NULL && outForward != NULL && outUp != NULL);
4666 switch (viewDirection)
4680 case VIEW_STARBOARD:
4695 case VIEW_GUI_DISPLAY:
4696 case VIEW_BREAK_PATTERN:
4706- (OOMatrix) activeViewMatrix
4711 [
self getActiveViewMatrix:&m forwardVector:&f upVector:&u];
4721- (void) defineFrustum
4729 frustum[0][0] = clip.m[0][3] - clip.m[0][0];
4730 frustum[0][1] = clip.m[1][3] - clip.m[1][0];
4731 frustum[0][2] = clip.m[2][3] - clip.m[2][0];
4732 frustum[0][3] = clip.m[3][3] - clip.m[3][0];
4735 rt = 1.0f / sqrt(frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2]);
4736 frustum[0][0] *= rt;
4737 frustum[0][1] *= rt;
4738 frustum[0][2] *= rt;
4739 frustum[0][3] *= rt;
4742 frustum[1][0] = clip.m[0][3] + clip.m[0][0];
4743 frustum[1][1] = clip.m[1][3] + clip.m[1][0];
4744 frustum[1][2] = clip.m[2][3] + clip.m[2][0];
4745 frustum[1][3] = clip.m[3][3] + clip.m[3][0];
4748 rt = 1.0f / sqrt(frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2]);
4749 frustum[1][0] *= rt;
4750 frustum[1][1] *= rt;
4751 frustum[1][2] *= rt;
4752 frustum[1][3] *= rt;
4755 frustum[2][0] = clip.m[0][3] + clip.m[0][1];
4756 frustum[2][1] = clip.m[1][3] + clip.m[1][1];
4757 frustum[2][2] = clip.m[2][3] + clip.m[2][1];
4758 frustum[2][3] = clip.m[3][3] + clip.m[3][1];
4761 rt = 1.0 / sqrt(frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2]);
4762 frustum[2][0] *= rt;
4763 frustum[2][1] *= rt;
4764 frustum[2][2] *= rt;
4765 frustum[2][3] *= rt;
4768 frustum[3][0] = clip.m[0][3] - clip.m[0][1];
4769 frustum[3][1] = clip.m[1][3] - clip.m[1][1];
4770 frustum[3][2] = clip.m[2][3] - clip.m[2][1];
4771 frustum[3][3] = clip.m[3][3] - clip.m[3][1];
4774 rt = 1.0 / sqrt(frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2]);
4775 frustum[3][0] *= rt;
4776 frustum[3][1] *= rt;
4777 frustum[3][2] *= rt;
4778 frustum[3][3] *= rt;
4781 frustum[4][0] = clip.m[0][3] - clip.m[0][2];
4782 frustum[4][1] = clip.m[1][3] - clip.m[1][2];
4783 frustum[4][2] = clip.m[2][3] - clip.m[2][2];
4784 frustum[4][3] = clip.m[3][3] - clip.m[3][2];
4787 rt = sqrt(frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2]);
4788 frustum[4][0] *= rt;
4789 frustum[4][1] *= rt;
4790 frustum[4][2] *= rt;
4791 frustum[4][3] *= rt;
4794 frustum[5][0] = clip.m[0][3] + clip.m[0][2];
4795 frustum[5][1] = clip.m[1][3] + clip.m[1][2];
4796 frustum[5][2] = clip.m[2][3] + clip.m[2][2];
4797 frustum[5][3] = clip.m[3][3] + clip.m[3][2];
4800 rt = sqrt(frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2]);
4801 frustum[5][0] *= rt;
4802 frustum[5][1] *= rt;
4803 frustum[5][2] *= rt;
4804 frustum[5][3] *= rt;
4808- (BOOL) viewFrustumIntersectsSphereAt:(Vector)position withRadius:(GLfloat)radius
4812 for (p = 0; p < 6; p++)
4814 if (frustum[p][0] * position.x + frustum[p][1] * position.y + frustum[p][2] * position.z + frustum[p][3] <= -radius)
4823- (void) drawUniverse
4825 int currentPostFX = [
self currentPostFX];
4827 NSSize viewSize = [gameView backingViewSize];
4828 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin draw");
4832 if ((
int)targetFramebufferSize.width != (
int)viewSize.width || (
int)targetFramebufferSize.height != (
int)viewSize.height)
4834 [
self resizeTargetFramebufferWithViewSize:viewSize];
4837 if([
self useShaders])
4839 if ([gameView msaa])
4841 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
4845 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
4852 int i, v_status, vdist;
4853 Vector view_dir, view_up;
4854 OOMatrix view_matrix;
4855 int ent_count = n_entities;
4856 Entity *my_entities[ent_count];
4862 float aspect = viewSize.height/viewSize.width;
4864 if (!displayGUI && wasDisplayGUI)
4867 if (cachedSun) [UNIVERSE setMainLightPosition:HPVectorToVector([cachedSun position])];
4868 else [UNIVERSE setMainLightPosition:kZeroVector];
4870 wasDisplayGUI = displayGUI;
4872 for (i = 0; i < ent_count; i++)
4879 Entity *e = sortedEntities[i];
4882 my_entities[draw_count++] = [[e retain] autorelease];
4886 v_status = [player
status];
4892 OOGL(glClear(GL_COLOR_BUFFER_BIT));
4896 OOGL(glClearColor(skyClearColor[0], skyClearColor[1], skyClearColor[2], skyClearColor[3]));
4900 OOGL(glClearColor(0.0, 0.0, 0.0, 0.0));
4904 [gui drawGUIBackground];
4908 BOOL fogging, bpHide = [
self breakPatternHide];
4912 for(
int i = 0; i < draw_count; i++ )
4914 if ([my_entities[i] cameraRangeFront] > breakPlane)
4918 if ([my_entities[i] cameraRangeBack] > breakPlane)
4925 float distanceFactor = sqrt(1 + ([gameView fov:YES]*[gameView fov:YES] * (1.0 + 1.0/(aspect*aspect))));
4927 for (vdist=0;vdist<=1;vdist++)
4931 float ratio = (displayGUI ? 0.5 : [gameView fov:YES]) * nearPlane / distanceFactor;
4934 if ((displayGUI && 4*aspect >= 3) || (!displayGUI && 4*aspect <= 3))
4936 OOGLFrustum(-ratio, ratio, -aspect*ratio, aspect*ratio, nearPlane / distanceFactor, farPlane);
4940 OOGLFrustum(-3*ratio/aspect/4, 3*ratio/aspect/4, -3*ratio/4, 3*ratio/4, nearPlane / distanceFactor, farPlane);
4943 [
self getActiveViewMatrix:&view_matrix forwardVector:&view_dir upVector:&view_up];
4975 OOGL(glClear(GL_DEPTH_BUFFER_BIT));
4980 flipMatrix.m[2][2] = -1;
4986 if (
EXPECT(!displayGUI || demoShipMode))
4988 if (
EXPECT(!demoShipMode))
4994 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
4998 [
self setMainLightPosition:[cachedSun cameraRelativePosition]];
5003 [
self setMainLightPosition:HPVectorToVector(HPvector_flip([PLAYER viewpointPosition]))];
5005 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, main_light_position));
5011 OOGL(glLightfv(GL_LIGHT0, GL_POSITION, main_light_position));
5013 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, main_light_position));
5017 OOGL([
self useGUILightSource:demoShipMode]);
5022 int furthest = draw_count - 1;
5024 BOOL inAtmosphere = airResistanceFactor > 0.01;
5025 GLfloat fogFactor = 0.5 / airResistanceFactor;
5026 double fog_scale, half_scale;
5027 GLfloat flat_ambdiff[4] = {1.0, 1.0, 1.0, 1.0};
5028 GLfloat mat_no[4] = {0.0, 0.0, 0.0, 1.0};
5031 OOGL(glHint(GL_FOG_HINT, [
self reducedDetail] ? GL_FASTEST : GL_NICEST));
5033 [
self defineFrustum];
5037 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin opaque pass");
5041 for (i = furthest; i >= nearest; i--)
5043 drawthing = my_entities[i];
5047 if ([drawthing lastDrawCounter] == drawCounter)
continue;
5048 if (vdist == 0 && [drawthing cameraRangeFront] < nearPlane)
5053 if (!((d_status == STATUS_COCKPIT_DISPLAY) ^ demoShipMode))
5057 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, flat_ambdiff));
5058 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_no));
5061 if (
EXPECT(drawthing != player))
5084 half_scale = fog_scale * 0.50;
5085 OOGL(glEnable(GL_FOG));
5086 OOGL(glFogi(GL_FOG_MODE, GL_LINEAR));
5087 OOGL(glFogfv(GL_FOG_COLOR, skyClearColor));
5088 OOGL(glFogf(GL_FOG_START, half_scale));
5089 OOGL(glFogf(GL_FOG_END, fog_scale));
5090 fog_blend = OOClamp_0_1_f((magnitude([drawthing cameraRelativePosition]) - half_scale)/half_scale);
5094 [
self lightForEntity:demoShipMode || drawthing->isSunlit];
5106 OOGL(glDisable(GL_FOG));
5111 if (!((d_status == STATUS_COCKPIT_DISPLAY) ^ demoShipMode))
5114 if (
EXPECT(drawthing != player))
5137 half_scale = fog_scale * 0.50;
5138 OOGL(glEnable(GL_FOG));
5139 OOGL(glFogi(GL_FOG_MODE, GL_LINEAR));
5140 OOGL(glFogfv(GL_FOG_COLOR, skyClearColor));
5141 OOGL(glFogf(GL_FOG_START, half_scale));
5142 OOGL(glFogf(GL_FOG_END, fog_scale));
5143 fog_blend = OOClamp_0_1_f((magnitude([drawthing cameraRelativePosition]) - half_scale)/half_scale);
5155 OOGL(glDisable(GL_FOG));
5172 if (!bpHide && cachedSun)
5174 [cachedSun drawDirectVisionSunGlare];
5175 [cachedSun drawStarGlare];
5180 if (hudSeparateRenderPass)
5185 [
self prepareToRenderIntoDefaultFramebuffer];
5186 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
5188 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"Begin second pass draw");
5189 [
self drawTargetTextureIntoDefaultFramebuffer];
5190 OOCheckOpenGLErrors(
@"Universe after drawing from custom framebuffer to screen framebuffer");
5191 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"End second pass drawing");
5193 OOLog(
@"universe.profile.drawHUD",
@"%@",
@"Begin HUD drawing");
5198 OOLog(
@"universe.profile.draw",
@"%@",
@"Begin HUD");
5200 GLfloat lineWidth = [gameView backingViewSize].width / 1024.0;
5201 if (lineWidth < 1.0) lineWidth = 1.0;
5202 if (lineWidth > 1.5) lineWidth = 1.5;
5209 if ([theHUD deferredHudName] !=
nil)
5213 [deferredName release];
5214 theHUD = [player
hud];
5218 static float sPrevHudAlpha = -1.0f;
5219 if ([theHUD isHidden])
5221 if (sPrevHudAlpha < 0.0f)
5227 else if (sPrevHudAlpha >= 0.0f)
5230 sPrevHudAlpha = -1.0f;
5235 case STATUS_ESCAPE_SEQUENCE:
5236 case STATUS_START_GAME:
5240 switch ([player guiScreen])
5254#if (defined (SNAPSHOT_BUILD))
5255 [
self drawWatermarkString:@"Development version " @OO_VERSION_FULL];
5258 OOLog(
@"universe.profile.drawHUD",
@"%@",
@"End HUD drawing");
5267 if (![[
self gameController] isGamePaused])
5269 framesDoneThisUpdate++;
5272 @catch (NSException *exception)
5276 if ([[exception name] hasPrefix:
@"Oolite"])
5278 [
self handleOoliteException:exception];
5282 OOLog(
kOOLogException,
@"***** Exception: %@ : %@ *****",[exception name], [exception reason]);
5288 OOLog(
@"universe.profile.draw",
@"%@",
@"End drawing");
5291 if(!hudSeparateRenderPass)
5293 if([
self useShaders])
5295 [
self prepareToRenderIntoDefaultFramebuffer];
5296 OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
5298 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"Begin second pass draw");
5299 [
self drawTargetTextureIntoDefaultFramebuffer];
5300 OOLog(
@"universe.profile.secondPassDraw",
@"%@",
@"End second pass drawing");
5308 NSSize viewSize = [gameView backingViewSize];
5309 if([
self useShaders])
5311 if ([gameView msaa])
5314 OOGL(glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFramebufferID));
5315 OOGL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFramebufferID));
5316 OOGL(glBlitFramebuffer(0, 0, (GLint)viewSize.width, (GLint)viewSize.height, 0, 0, (GLint)viewSize.width, (GLint)viewSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
5322- (
int) framesDoneThisUpdate
5324 return framesDoneThisUpdate;
5328- (void) resetFramesDoneThisUpdate
5330 framesDoneThisUpdate = 0;
5334- (OOMatrix) viewMatrix
5344 OOGL(glDisable(GL_TEXTURE_2D));
5346 float overallAlpha = [[PLAYER hud] overallAlpha];
5351 cursor_row = [gui drawGUI:1.0 drawCursor:YES];
5355 [gui drawGUI:1.0 drawCursor:NO];
5359 [message_gui drawGUI:[message_gui alpha] * overallAlpha drawCursor:NO];
5360 [comm_log_gui drawGUI:[comm_log_gui alpha] * overallAlpha drawCursor:NO];
5366- (void) drawWatermarkString:(NSString *) watermarkString
5368 NSSize watermarkStringSize =
OORectFromString(watermarkString, 0.0f, 0.0f, NSMakeSize(10, 10)).size;
5370 OOGL(glColor4f(0.0, 1.0, 0.0, 1.0));
5384 OOLog(
@"universe.badUID",
@"Attempt to retrieve entity for out-of-range UID %u. (This is an internal programming error, please report it.)", u_id);
5388 if ((u_id ==
NO_TARGET)||(!entity_for_uid[u_id]))
5391 Entity *ent = entity_for_uid[u_id];
5397 if ([ent status] == STATUS_DEAD || [ent status] == STATUS_DOCKED)
5408 NSCParameterAssert(uni != NULL);
5421 while ((n--)&&(checkEnt))
5424 checkEnt = checkEnt->
x_next;
5426 if ((checkEnt)||(n > 0))
5434 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
x_previous;
5435 if ((checkEnt)||(n > 0))
5446 checkEnt = checkEnt->
x_next;
5454 while ((n--)&&(checkEnt))
5457 checkEnt = checkEnt->
y_next;
5459 if ((checkEnt)||(n > 0))
5467 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
y_previous;
5468 if ((checkEnt)||(n > 0))
5479 checkEnt = checkEnt->
y_next;
5487 while ((n--)&&(checkEnt))
5490 checkEnt = checkEnt->
z_next;
5492 if ((checkEnt)||(n > 0))
5500 while ((n--)&&(checkEnt)) checkEnt = checkEnt->
z_previous;
5501 if ((checkEnt)||(n > 0))
5508 NSCAssert(checkEnt !=
nil,
@"Expected z-list to be non-empty.");
5513 checkEnt = checkEnt->
z_next;
5523 NSArray *allEntities = uni->
entities;
5529 foreach (ent, allEntities)
5545- (BOOL) addEntity:(
Entity *) entity
5553 if (![entity validForAddToUniverse])
return NO;
5556 if ([entities containsObject:entity])
5562 OOLog(
@"universe.addEntity.failed",
@"***** Universe cannot addEntity:%@ -- Universe is full (%d entities out of %d)", entity, n_entities,
UNIVERSE_MAX_ENTITIES);
5569 if (![entity isEffect])
5572 while (entity_for_uid[next_universal_id] !=
nil)
5574 next_universal_id++;
5582 OOLog(
@"universe.addEntity.failed",
@"***** Universe cannot addEntity:%@ -- Could not find free slot for entity.", entity);
5587 entity_for_uid[next_universal_id] = entity;
5588 if ([entity isShip])
5593 [
self setNextBeacon:se];
5600 double stationRoll = 0.0;
5604 if (definedRoll !=
nil)
5610 stationRoll = [[
self currentSystemData] oo_doubleForKey:@"station_roll" defaultValue:STANDARD_STATION_ROLL];
5623 if ([se status] != STATUS_COCKPIT_DISPLAY)
5632 if ([entity isVisualEffect])
5637 [
self setNextBeacon:ve];
5640 else if ([entity isWaypoint])
5645 [
self setNextBeacon:wp];
5655 [entities addObject:entity];
5659 HPVector entity_pos = entity->
position;
5660 HPVector delta = HPvector_between(entity_pos,
PLAYER->position);
5661 double z_distance = HPmagnitude2(delta);
5663 unsigned index = n_entities;
5664 sortedEntities[index] = entity;
5666 while ((index > 0)&&(z_distance < sortedEntities[index - 1]->zero_distance))
5668 sortedEntities[index] = sortedEntities[index - 1];
5669 sortedEntities[index]->zero_index = index;
5671 sortedEntities[index] = entity;
5680 if ([entity canCollide])
5682 doLinkedListMaintenanceThisUpdate = YES;
5685 if ([entity isWormhole])
5687 [activeWormholes addObject:entity];
5689 else if ([entity isPlanet])
5691 [allPlanets addObject:entity];
5693 else if ([entity isShip])
5697 if ([entity isStation])
5699 [allStations addObject:entity];
5709- (BOOL) removeEntity:(
Entity *) entity
5711 if (entity !=
nil && ![entity isPlayer])
5717 [entitiesDeadThisUpdate addObject:entity];
5718 if ([entity isStation])
5720 [allStations removeObject:entity];
5721 if ([
PLAYER getTargetDockStation] == entity)
5723 [PLAYER setDockingClearanceStatus:DOCKING_CLEARANCE_STATUS_NONE];
5726 return [
self doRemoveEntity:entity];
5732- (void) ensureEntityReallyRemoved:(
Entity *)entity
5736 OOLog(
@"universe.unremovedEntity",
@"Entity %@ dealloced without being removed from universe! (This is an internal programming error, please report it.)", entity);
5737 [
self doRemoveEntity:entity];
5742- (void) removeAllEntitiesExceptPlayer
5744 BOOL updating = no_update;
5748 Entity* p0 = [entities objectAtIndex:0];
5757 NSMutableArray *savedWormholes = [activeWormholes mutableCopy];
5759 while ([entities
count] > 1)
5761 Entity* ent = [entities objectAtIndex:1];
5764 if (
EXPECT(![ent isVisualEffect]))
5766 [
self removeEntity:ent];
5775 [activeWormholes release];
5776 activeWormholes = savedWormholes;
5783 cachedStation =
nil;
5784 [closeSystems release];
5787 [
self resetBeacons];
5788 [waypoints removeAllObjects];
5790 no_update = updating;
5794- (void) removeDemoShips
5797 int ent_count = n_entities;
5801 for (i = 0; i < ent_count; i++)
5803 ent = sortedEntities[i];
5804 if ([ent status] == STATUS_COCKPIT_DISPLAY && ![ent isPlayer])
5806 [
self removeEntity:ent];
5814- (
ShipEntity *) makeDemoShipWithRole:(NSString *)role spinning:(BOOL)spinning
5818 [
self removeDemoShips];
5820 [PLAYER setShowDemoShips: YES];
5821 Quaternion q2 = { (GLfloat)
M_SQRT1_2, (GLfloat)
M_SQRT1_2, (GLfloat)0.0, (GLfloat)0.0 };
5823 ShipEntity *ship = [
self newShipWithRole:role];
5833 [UNIVERSE addEntity:ship];
5843 [ship
setStatus:STATUS_COCKPIT_DISPLAY];
5850 return [ship autorelease];
5854- (BOOL) isVectorClearFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5862 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5864 double nearest = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z) - dist;
5870 int ent_count = n_entities;
5871 Entity* my_entities[ent_count];
5872 for (i = 0; i < ent_count; i++)
5873 my_entities[i] = [sortedEntities[i] retain];
5875 if (v1.x || v1.y || v1.z)
5876 f1 = HPvector_normal(v1);
5878 f1 = make_HPvector(0, 0, 1);
5880 for (i = 0; i < ent_count ; i++)
5882 Entity *e2 = my_entities[i];
5883 if ((e2 != e1)&&([e2 canCollide]))
5886 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5888 double d_forward = HPdot_product(epos,f1);
5890 if ((d_forward > 0)&&(d_forward < nearest))
5894 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5897 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5899 double dist2 = p0.x * p0.x + p0.
y * p0.
y + p0.z * p0.z;
5902 for (i = 0; i < ent_count; i++)
5903 [my_entities[i] release];
5909 for (i = 0; i < ent_count; i++)
5910 [my_entities[i] release];
5915- (
Entity*) hazardOnRouteFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5923 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5925 double nearest = HPmagnitude(v1) - dist;
5932 int ent_count = n_entities;
5933 Entity* my_entities[ent_count];
5934 for (i = 0; i < ent_count; i++)
5935 my_entities[i] = [sortedEntities[i] retain];
5937 if (v1.x || v1.y || v1.z)
5938 f1 = HPvector_normal(v1);
5940 f1 = make_HPvector(0, 0, 1);
5942 for (i = 0; (i < ent_count) && (!result) ; i++)
5944 Entity *e2 = my_entities[i];
5945 if ((e2 != e1)&&([e2 canCollide]))
5948 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
5950 double d_forward = HPdot_product(epos,f1);
5952 if ((d_forward > 0)&&(d_forward < nearest))
5956 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
5959 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
5961 double dist2 = HPmagnitude2(p0);
5967 for (i = 0; i < ent_count; i++)
5968 [my_entities[i] release];
5973- (HPVector) getSafeVectorFromEntity:(
Entity *) e1 toDistance:(
double)dist fromPoint:(HPVector) p2
5984 HPVector result = p2;
5986 int ent_count = n_entities;
5987 Entity* my_entities[ent_count];
5988 for (i = 0; i < ent_count; i++)
5989 my_entities[i] = [sortedEntities[i] retain];
5992 v1.x -= p1.
x; v1.y -= p1.
y; v1.z -= p1.z;
5994 double nearest = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z) - dist;
5996 if (v1.x || v1.y || v1.z)
5997 f1 = HPvector_normal(v1);
5999 f1 = make_HPvector(0, 0, 1);
6001 for (i = 0; i < ent_count; i++)
6003 Entity *e2 = my_entities[i];
6004 if ((e2 != e1)&&([e2 canCollide]))
6007 epos.x -= p1.
x; epos.y -= p1.
y; epos.z -= p1.z;
6008 double d_forward = HPdot_product(epos,f1);
6009 if ((d_forward > 0)&&(d_forward < nearest))
6014 p0.x += d_forward * f1.
x; p0.y += d_forward * f1.
y; p0.z += d_forward * f1.z;
6018 p0.x -= epos.
x; p0.y -= epos.
y; p0.z -= epos.z;
6021 double dist2 = p0.x * p0.x + p0.
y * p0.
y + p0.z * p0.z;
6026 nearest = d_forward;
6032 result.x += ((
int)(
Ranrot() % 1024) - 512)/512.0;
6033 result.y += ((
int)(
Ranrot() % 1024) - 512)/512.0;
6034 result.z += ((
int)(
Ranrot() % 1024) - 512)/512.0;
6037 HPVector nearest_point = p1;
6038 nearest_point.x += d_forward * f1.
x; nearest_point.y += d_forward * f1.
y; nearest_point.z += d_forward * f1.z;
6041 HPVector outward = nearest_point;
6042 outward.x -= result.
x; outward.y -= result.
y; outward.z -= result.z;
6043 if (outward.x||outward.y||outward.z)
6044 outward = HPvector_normal(outward);
6049 HPVector backward = p1;
6050 backward.x -= result.
x; backward.y -= result.
y; backward.z -= result.z;
6051 if (backward.x||backward.y||backward.z)
6052 backward = HPvector_normal(backward);
6057 HPVector dd = result;
6058 dd.x -= p1.
x; dd.y -= p1.
y; dd.z -= p1.z;
6059 double current_distance = HPmagnitude(dd);
6062 if (current_distance < cr * 1.25)
6063 current_distance = cr * 1.25;
6064 if (current_distance > cr * 5.0)
6065 current_distance = cr * 5.0;
6069 result.x += 0.25 * (outward.
x * current_distance) + 0.75 * (backward.
x * current_distance);
6070 result.y += 0.25 * (outward.
y * current_distance) + 0.75 * (backward.
y * current_distance);
6071 result.z += 0.25 * (outward.z * current_distance) + 0.75 * (backward.z * current_distance);
6077 for (i = 0; i < ent_count; i++)
6078 [my_entities[i] release];
6083- (
ShipEntity*) addWreckageFrom:(
ShipEntity *)ship withRole:(NSString *)wreckRole at:(HPVector)rpos scale:(GLfloat)scale lifetime:(GLfloat)lifetime
6085 ShipEntity* wreck = [UNIVERSE newShipWithRole:wreckRole];
6089 GLfloat expected_mass = 0.1f * [ship
mass] * (0.75 + 0.5 *
randf());
6090 GLfloat wreck_mass = [wreck
mass];
6091 GLfloat scale_factor = powf(expected_mass / wreck_mass, 0.33333333f) * scale;
6107 [UNIVERSE addEntity:wreck];
6117- (void) addLaserHitEffectsAt:(HPVector)pos against:(
ShipEntity *)target damage:(
float)damage color:(
OOColor *)color
6120 if ([target showDamage] && [target energy] < [target maxEnergy]/2)
6122 NSString *key = (
randf() < 0.5) ?
@"oolite-hull-spark" :
@"oolite-hull-spark-b";
6123 NSDictionary *settings = [UNIVERSE explosionSetting:key];
6126 [
self addEntity: burst];
6127 if ([target energy] *
randf() < damage)
6129 ShipEntity *wreck = [
self addWreckageFrom:target withRole:@"oolite-wreckage-chunk" at:pos scale:0.05 lifetime:(125.0+(randf()*200.0))];
6132 Vector direction = HPVectorToVector(HPvector_normal(HPvector_subtract(pos,[target position])));
6133 [wreck
setVelocity:vector_add([wreck
velocity],vector_multiply_scalar(direction,10+20*randf()))];
6144- (
ShipEntity *) firstShipHitByLaserFromShip:(
ShipEntity *)srcEntity inDirection:(
OOWeaponFacing)direction offset:(Vector)offset gettingRangeFound:(GLfloat *)range_ptr
6146 if (srcEntity ==
nil)
return nil;
6150 HPVector p0 = [srcEntity
position];
6158 HPVector midfrontplane = make_HPvector(0.5 * (bbox.max.x + bbox.min.x), 0.5 * (bbox.max.y + bbox.min.y), bbox.max.z);
6161 if ([parent isPlayer]) q1.w = -q1.w;
6166 int ent_count = n_entities;
6170 for (i = 0; i < ent_count; i++)
6172 Entity* ent = sortedEntities[i];
6173 if (ent != srcEntity && ent != parent && [ent isShip] && [ent canCollide])
6204 HPVector p1 = HPvector_add(p0, vectorToHPVector(vector_multiply_scalar(f1, nearest)));
6206 for (i = 0; i < ship_count; i++)
6212 Vector rpos = HPVectorToVector(HPvector_subtract(e2->
position, p0));
6213 Vector v_off = make_vector(dot_product(rpos, r1), dot_product(rpos, u1), dot_product(rpos, f1));
6214 if (v_off.z > 0.0 && v_off.z < nearest + cr &&
6215 v_off.x < cr && v_off.x > -cr && v_off.y < cr && v_off.y > -cr &&
6216 v_off.x * v_off.x + v_off.y * v_off.y < cr * cr)
6219 GLfloat hit = [(
ShipEntity *)
e2 doesHitLine:p0 :p1 :&entHit];
6221 if (hit > 0.0 && hit < nearest)
6223 if ([entHit isSubEntity])
6225 hit_subentity = entHit;
6229 p1 = HPvector_add(p0, vectorToHPVector(vector_multiply_scalar(f1, nearest)));
6239 if (range_ptr != NULL)
6241 *range_ptr = nearest;
6245 for (i = 0; i < ship_count; i++) [my_entities[i] release];
6251- (
Entity *) firstEntityTargetedByPlayer
6256 nearest2 *= nearest2;
6258 int ent_count = n_entities;
6260 Entity *my_entities[ent_count];
6262 for (i = 0; i < ent_count; i++)
6264 if (([sortedEntities[i] isShip] && ![sortedEntities[i] isPlayer]) || [sortedEntities[i] isWormhole])
6266 my_entities[ship_count++] = [sortedEntities[i] retain];
6278 switch (viewDirection)
6286 case VIEW_STARBOARD :
6294 for (i = 0; i < ship_count; i++)
6296 Entity *e2 = my_entities[i];
6297 if ([e2 canCollide] && [e2 scanClass] != CLASS_NO_DRAW)
6299 Vector rp = HPVectorToVector(HPvector_subtract([e2 position], p1));
6301 if (dist2 < nearest2)
6304 if (df > 0.0 && df * df < nearest2)
6309 if (du * du + dr * dr < cr * cr)
6319 if (hit_entity !=
nil && [hit_entity isShip])
6322 if ([ship isJammingScanning] && ![player hasMilitaryScannerFilter])
6328 for (i = 0; i < ship_count; i++)
6330 [my_entities[i] release];
6337- (
Entity *) firstEntityTargetedByPlayerPrecisely
6343 switch (viewDirection)
6360 case VIEW_STARBOARD:
6371 return [
self firstShipHitByLaserFromShip:PLAYER inDirection:targetFacing offset:laserPortOffset gettingRangeFound:NULL];
6375- (NSArray *) entitiesWithinRange:(
double)range ofEntity:(
Entity *)entity
6377 if (entity ==
nil)
return nil;
6379 return [
self findShipsMatchingPredicate:YESPredicate
6386- (unsigned) countShipsWithRole:(NSString *)role inRange:(
double)range ofEntity:(
Entity *)entity
6388 return [
self countShipsMatchingPredicate:HasRolePredicate
6395- (unsigned) countShipsWithRole:(NSString *)role
6397 return [
self countShipsWithRole:role inRange:-1 ofEntity:nil];
6401- (unsigned) countShipsWithPrimaryRole:(NSString *)role inRange:(
double)range ofEntity:(
Entity *)entity
6403 return [
self countShipsMatchingPredicate:HasPrimaryRolePredicate
6410- (unsigned) countShipsWithScanClass:(
OOScanClass)scanClass inRange:(
double)range ofEntity:(
Entity *)entity
6412 return [
self countShipsMatchingPredicate:HasScanClassPredicate
6413 parameter:[NSNumber numberWithInt:scanClass]
6419- (unsigned) countShipsWithPrimaryRole:(NSString *)role
6421 return [
self countShipsWithPrimaryRole:role inRange:-1 ofEntity:nil];
6426 parameter:(
void *)parameter
6427 inRange:(
double)range
6430 unsigned i, found = 0;
6432 double distance, cr;
6439 for (i = 0; i < n_entities; i++)
6441 Entity *e2 = sortedEntities[i];
6442 if (e2 != e1 && predicate(e2, parameter))
6444 if (range < 0) distance = -1;
6447 cr = range + e2->collision_radius;
6448 distance = HPdistance2(e2->
position, p1) - cr * cr;
6462 parameter:(
void *)parameter
6463 inRange:(
double)range
6464 ofEntity:(
Entity *)entity
6466 if (predicate != NULL)
6471 predicate, parameter
6474 return [
self countEntitiesMatchingPredicate:ANDPredicate
6481 return [
self countEntitiesMatchingPredicate:IsShipPredicate
6491 if (range < 0)
return YES;
6493 return HPdistance2(e2->
position,p1) < cr * cr;
6500 parameter:(
void *)parameter
6501 inRange:(
double)range
6508 NSMutableArray *result =
nil;
6514 result = [NSMutableArray arrayWithCapacity:n_entities];
6519 for (i = 0; i < n_entities; i++)
6521 Entity *e2 = sortedEntities[i];
6525 predicate(e2, parameter))
6527 [result addObject:e2];
6540 parameter:(
void *)parameter
6549 for (i = 0; i < n_entities; i++)
6551 candidate = sortedEntities[i];
6552 if (predicate(candidate, parameter))
return candidate;
6562 parameter:(
void *)parameter
6563 inRange:(
double)range
6564 ofEntity:(
Entity *)entity
6566 if (predicate != NULL)
6571 predicate, parameter
6574 return [
self findEntitiesMatchingPredicate:ANDPredicate
6581 return [
self findEntitiesMatchingPredicate:IsShipPredicate
6590 parameter:(
void *)parameter
6591 inRange:(
double)range
6592 ofEntity:(
Entity *)entity
6594 if (predicate != NULL)
6599 predicate, parameter
6602 return [
self findEntitiesMatchingPredicate:ANDPredicate
6609 return [
self findEntitiesMatchingPredicate:IsVisualEffectPredicate
6618 parameter:(
void *)parameter
6619 relativeToEntity:(
Entity *)entity
6623 float rangeSq = INFINITY;
6631 for (i = 0; i < n_entities; i++)
6633 Entity *e2 = sortedEntities[i];
6634 float distanceToReferenceEntitySquared = (float)HPdistance2(p1, [e2 position]);
6637 distanceToReferenceEntitySquared < rangeSq &&
6638 predicate(e2, parameter))
6641 rangeSq = distanceToReferenceEntitySquared;
6645 return [[result retain] autorelease];
6650 parameter:(
void *)parameter
6651 relativeToEntity:(
Entity *)entity
6653 if (predicate != NULL)
6658 predicate, parameter
6661 return [
self nearestEntityMatchingPredicate:ANDPredicate
6663 relativeToEntity:entity];
6667 return [
self nearestEntityMatchingPredicate:IsShipPredicate
6669 relativeToEntity:entity];
6676 return universal_time;
6686- (void) findCollisionsAndShadows
6690 [universeRegion clearEntityList];
6692 for (i = 0; i < n_entities; i++)
6694 [universeRegion checkEntity:sortedEntities[i]];
6697 if (![[
self gameController] isGamePaused])
6699 [universeRegion findCollisions];
6703 [universeRegion findShadowedEntities];
6707- (NSString*) collisionDescription
6709 if (universeRegion !=
nil)
return [universeRegion collisionDescription];
6714- (void) dumpCollisions
6716 dumpCollisionInfo = YES;
6722 return viewDirection;
6726- (void) setViewDirection:(
OOViewID) vd
6729 BOOL guiSelected = NO;
6731 if ((viewDirection == vd) && (vd != VIEW_CUSTOM) && (!displayGUI))
6737 ms =
DESC(
@"forward-view-string");
6741 ms =
DESC(
@"aft-view-string");
6745 ms =
DESC(
@"port-view-string");
6748 case VIEW_STARBOARD:
6749 ms =
DESC(
@"starboard-view-string");
6753 ms = [PLAYER customViewDescription];
6756 case VIEW_GUI_DISPLAY:
6757 [
self setDisplayText:YES];
6758 [
self setMainLightPosition:(Vector){ DEMO_LIGHT_POSITION }];
6769 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
6774 [[
self gameController] setMouseInteractionModeForFlight];
6777 if (viewDirection != vd || viewDirection == VIEW_CUSTOM)
6779 #if (ALLOW_CUSTOM_VIEWS_WHILE_PAUSED)
6780 BOOL gamePaused = [[
self gameController] isGamePaused];
6782 BOOL gamePaused = NO;
6787 if (ms && !gamePaused)
6789 [
self addMessage:ms forCount:3];
6791 else if (gamePaused)
6793 [message_gui clear];
6799- (void) enterGUIViewModeWithMouseInteraction:(BOOL)mouseInteraction
6802 [
self setViewDirection:VIEW_GUI_DISPLAY];
6803 if (viewDirection != vd) {
6809 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:mouseInteraction];
6813- (NSString *) soundNameForCustomSoundKey:(NSString *)key
6815 NSString *result =
nil;
6816 NSMutableSet *seen =
nil;
6817 id object = [customSounds objectForKey:key];
6819 if ([
object isKindOfClass:[NSArray class]] && [object
count] > 0)
6821 key = [object oo_stringAtIndex:Ranrot() % [object count]];
6832 seen = [NSMutableSet set];
6834 if (
object ==
nil || ([result hasPrefix:
@"["] && [result hasSuffix:
@"]"]))
6838 [seen addObject:result];
6839 object = [customSounds objectForKey:result];
6840 if( [
object isKindOfClass:[NSArray class]] && [object
count] > 0)
6842 result = [object oo_stringAtIndex:Ranrot() % [object count]];
6843 if ([key hasPrefix:
@"["] && [key hasSuffix:
@"]"]) key=result;
6847 if ([
object isKindOfClass:[NSString class]])
6852 if (result ==
nil || ![result hasPrefix:
@"["] || ![result hasSuffix:
@"]"]) break;
6853 if ([seen containsObject:result])
6855 OOLogERR(
@"sound.customSounds.recursion",
@"recursion in customsounds.plist for '%@' (at '%@'), no sound will be played.", key, result);
6862 if (result ==
nil) result =
@"__oolite-no-sound";
6866 if ([result isEqualToString:
@"__oolite-no-sound"])
6868 OOLog(
@"sound.customSounds",
@"Could not resolve sound name in customsounds.plist for '%@', no sound will be played.", key);
6875- (NSDictionary *) screenTextureDescriptorForKey:(NSString *)key
6877 id value = [screenBackgrounds objectForKey:key];
6878 while ([value isKindOfClass:[NSArray class]]) value = [value objectAtIndex:
Ranrot() % [value
count]];
6880 if ([value isKindOfClass:[NSString class]]) value = [NSDictionary dictionaryWithObject:value forKey:
@"name"];
6881 else if (![value isKindOfClass:[NSDictionary class]]) value =
nil;
6884 if (![[
self gui] preloadGUITexture:value]) value =
nil;
6890- (void) setScreenTextureDescriptorForKey:(NSString *)key descriptor:(NSDictionary *)desc
6892 NSMutableDictionary *sbCopy = [screenBackgrounds mutableCopy];
6895 [sbCopy removeObjectForKey:key];
6899 [sbCopy setObject:desc forKey:key];
6901 [screenBackgrounds release];
6902 screenBackgrounds = [sbCopy copy];
6907- (void) clearPreviousMessage
6909 if (currentMessage) [currentMessage release];
6910 currentMessage =
nil;
6914- (void) setMessageGuiBackgroundColor:(
OOColor *)some_color
6916 [message_gui setBackgroundColor:some_color];
6920- (void) displayMessage:(NSString *) text forCount:(
OOTimeDelta)count
6922 if (![currentMessage isEqual:text] || universal_time >= messageRepeatTime)
6924 if (currentMessage) [currentMessage release];
6925 currentMessage = [text retain];
6926 messageRepeatTime=universal_time + 6.0;
6927 [
self showGUIMessage:text withScroll:YES andColor:[message_gui textColor] overDuration:count];
6932- (void) displayCountdownMessage:(NSString *) text forCount:(
OOTimeDelta)count
6934 if (![currentMessage isEqual:text] && universal_time >= countdown_messageRepeatTime)
6936 if (currentMessage) [currentMessage release];
6937 currentMessage = [text retain];
6938 countdown_messageRepeatTime=universal_time +
count;
6939 [
self showGUIMessage:text withScroll:NO andColor:[message_gui textColor] overDuration:count];
6944- (void) addDelayedMessage:(NSString *)text forCount:(
OOTimeDelta)count afterDelay:(
double)delay
6946 NSMutableDictionary *msgDict = [NSMutableDictionary dictionaryWithCapacity:2];
6947 [msgDict setObject:text forKey:@"message"];
6948 [msgDict setObject:[NSNumber numberWithDouble:count] forKey:@"duration"];
6949 [
self performSelector:@selector(addDelayedMessage:) withObject:msgDict afterDelay:delay];
6953- (void) addDelayedMessage:(NSDictionary *) textdict
6955 NSString *msg =
nil;
6958 msg = [textdict oo_stringForKey:@"message"];
6959 if (msg ==
nil)
return;
6960 msg_duration = [textdict oo_nonNegativeDoubleForKey:@"duration" defaultValue:3.0];
6962 [
self addMessage:msg forCount:msg_duration];
6966- (void) addMessage:(NSString *)text forCount:(
OOTimeDelta)count
6968 [
self addMessage:text forCount:count forceDisplay:NO];
6972- (void) speakWithSubstitutions:(NSString *)text
6974#if OOLITE_SPEECH_SYNTH
6980 NSString *systemSaid =
nil;
6981 NSString *h_systemSaid =
nil;
6983 NSString *systemName = [
self getSystemName:systemID];
6985 systemSaid = systemName;
6987 NSString *h_systemName = [
self getSystemName:[player
targetSystemID]];
6988 h_systemSaid = h_systemName;
6990 NSString *spokenText = text;
6991 if (speechArray !=
nil)
6993 NSArray *thePair =
nil;
6995 foreach (thePair, speechArray)
6997 NSString *original_phrase = [thePair oo_stringAtIndex:0];
6999 NSUInteger replacementIndex;
7001 replacementIndex = 1;
7003 replacementIndex = [thePair count] > 2 ? 2 : 1;
7006 NSString *replacement_phrase = [thePair oo_stringAtIndex:replacementIndex];
7007 if (![replacement_phrase isEqualToString:
@"_"])
7009 spokenText = [spokenText stringByReplacingOccurrencesOfString:original_phrase withString:replacement_phrase];
7012 spokenText = [spokenText stringByReplacingOccurrencesOfString:systemName withString:systemSaid];
7013 spokenText = [spokenText stringByReplacingOccurrencesOfString:h_systemName withString:h_systemSaid];
7015 [
self stopSpeaking];
7016 [
self startSpeakingString:spokenText];
7022- (void) addMessage:(NSString *) text forCount:(
OOTimeDelta) count forceDisplay:(BOOL) forceDisplay
7024 if (![currentMessage isEqual:text] || forceDisplay || universal_time >= messageRepeatTime)
7028 [
self speakWithSubstitutions:text];
7031 [
self showGUIMessage:text withScroll:YES andColor:[message_gui textColor] overDuration:count];
7033 [PLAYER doScriptEvent:OOJSID("consoleMessageReceived") withArgument:text];
7035 [currentMessage release];
7036 currentMessage = [text retain];
7037 messageRepeatTime=universal_time + 6.0;
7042- (void) addCommsMessage:(NSString *)text forCount:(
OOTimeDelta)count
7044 [
self addCommsMessage:text forCount:count andShowComms:_autoCommLog logOnly:NO];
7048- (void) addCommsMessage:(NSString *)text forCount:(
OOTimeDelta)count andShowComms:(BOOL)showComms logOnly:(BOOL)logOnly
7050 if ([
PLAYER showDemoShips])
return;
7052 NSString *expandedMessage =
OOExpand(text);
7054 if (![currentMessage isEqualToString:expandedMessage] || universal_time >= messageRepeatTime)
7063 NSString *format =
OOExpandKey(
@"speech-synthesis-incoming-message-@");
7064 [
self speakWithSubstitutions:[NSString stringWithFormat:format, expandedMessage]];
7067 [
self showGUIMessage:expandedMessage withScroll:YES andColor:[message_gui textCommsColor] overDuration:count];
7069 [currentMessage release];
7070 currentMessage = [expandedMessage retain];
7071 messageRepeatTime=universal_time + 6.0;
7074 [comm_log_gui printLongText:expandedMessage align:GUI_ALIGN_LEFT color:nil fadeTime:0.0 key:nil addToArray:[player
commLog]];
7076 if (showComms) [
self showCommsLog:6.0];
7083 [comm_log_gui setAlpha:1.0];
7084 if (![
self permanentCommLog]) [comm_log_gui fadeOutFromTime:[
self getTime] overDuration:how_long];
7088- (void) showGUIMessage:(NSString *)text withScroll:(BOOL)scroll andColor:(
OOColor *)selectedColor overDuration:(
OOTimeDelta)how_long
7092 [message_gui printLongText:text align:GUI_ALIGN_CENTER color:selectedColor fadeTime:how_long key:nil addToArray:nil];
7096 [message_gui printLineNoScroll:text align:GUI_ALIGN_CENTER color:selectedColor fadeTime:how_long key:nil addToArray:nil];
7098 [message_gui setAlpha:1.0f];
7102- (void) repopulateSystem
7109 [PLAYER doWorldScriptEvent:OOJSIDFromString(system_repopulator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
7117 volatile OOTimeDelta delta_t = inDeltaT * [
self timeAccelerationFactor];
7118 NSUInteger sessionID = _sessionID;
7119 OOLog(
@"universe.profile.update",
@"%@",
@"Begin update");
7122 next_repopulation -= delta_t;
7123 if (next_repopulation < 0)
7125 [
self repopulateSystem];
7128 unsigned i, ent_count = n_entities;
7129 Entity *my_entities[ent_count];
7131 [
self verifyEntitySessionIDs];
7134 for (i = 0; i < ent_count; i++)
7136 my_entities[i] = [sortedEntities[i] retain];
7139 NSString *
volatile update_stage =
@"initialisation";
7141 id volatile update_stage_param =
nil;
7148 skyClearColor[0] = 0.0;
7149 skyClearColor[1] = 0.0;
7150 skyClearColor[2] = 0.0;
7151 skyClearColor[3] = 0.0;
7153 time_delta = delta_t;
7154 universal_time += delta_t;
7156 if (
EXPECT_NOT([player showDemoShips] && [player guiScreen] == GUI_SCREEN_SHIPLIBRARY))
7158 update_stage =
@"demo management";
7160 if (universal_time >= demo_stage_time)
7172 [demo_ship setPosition:[demo_ship destination]];
7174 demo_stage_time = universal_time + 300.0;
7178 [demo_ship setVelocity:vel];
7180 demo_stage_time = universal_time + 0.25;
7184 [
self removeEntity:demo_ship];
7191 demo_ship_subindex = (demo_ship_subindex + 1) % [[demo_ships objectAtIndex:demo_ship_index] count];
7192 demo_ship = [
self newShipWithName:[[
self demoShipData] oo_stringForKey:kOODemoShipKey] usePlayerProxy:NO];
7194 if (demo_ship !=
nil)
7196 [demo_ship removeEquipmentItem:@"EQ_SHIELD_BOOSTER"];
7197 [demo_ship removeEquipmentItem:@"EQ_SHIELD_ENHANCER"];
7199 [demo_ship switchAITo:@"nullAI.plist"];
7200 [demo_ship setOrientation:q2];
7201 [demo_ship setScanClass: CLASS_NO_DRAW];
7202 [demo_ship setStatus: STATUS_COCKPIT_DISPLAY];
7203 [demo_ship setDemoShip: 1.0f];
7204 [demo_ship setDemoStartTime: universal_time];
7205 if ([
self addEntity:demo_ship])
7207 [demo_ship release];
7208 [demo_ship setStatus:STATUS_COCKPIT_DISPLAY];
7210 [demo_ship setPositionX:0.0f y:0.0f z:demo_start_z];
7211 [demo_ship setDestination: make_HPvector(0.0f, 0.0f, demo_start_z * 0.01f)];
7212 [demo_ship setVelocity:kZeroVector];
7213 [demo_ship setScanClass: CLASS_NO_DRAW];
7216 [
self setLibraryTextForDemoShip];
7219 demo_start_time=universal_time;
7234 [demo_ship setPositionX:0.0f y:[demo_ship destination].y * delta z:demo_start_z + ([demo_ship destination].z - demo_start_z) * delta ];
7238 update_stage =
@"update:entity";
7239 NSMutableSet *zombies =
nil;
7240 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7241 for (i = 0; i < ent_count; i++)
7243 Entity *thing = my_entities[i];
7245 update_stage_param = thing;
7246 update_stage =
@"update:entity [%@]";
7249 if (
EXPECT_NOT([thing status] == STATUS_DEAD && ![entitiesDeadThisUpdate containsObject:thing] && ![thing isPlayer]))
7251 if (zombies ==
nil) zombies = [NSMutableSet set];
7252 [zombies addObject:thing];
7264 update_stage =
@"update:list maintenance [%@]";
7271 while (index > 0 && z_distance < sortedEntities[index - 1]->zero_distance)
7273 sortedEntities[index] = sortedEntities[index - 1];
7274 sortedEntities[index - 1] = thing;
7276 sortedEntities[index]->zero_index = index;
7284 update_stage =
@"update:think [%@]";
7290 if ((universal_time > thinkTime)||(thinkTime == 0.0))
7299 update_stage_param =
nil;
7304 update_stage =
@"shootin' zombies";
7306 foreach (zombie, zombies)
7308 OOLogERR(
@"universe.zombie",
@"Found dead entity %@ in active entity list, removing. This is an internal error, please report it.", zombie);
7309 [
self removeEntity:zombie];
7314 update_stage =
@"updating linked lists";
7315 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7316 for (i = 0; i < ent_count; i++)
7323 update_stage =
@"collision and shadow detection";
7324 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7325 [
self filterSortedLists];
7326 [
self findCollisionsAndShadows];
7330 if (doLinkedListMaintenanceThisUpdate)
7333 doLinkedListMaintenanceThisUpdate = NO;
7336 @catch (NSException *exception)
7338 if ([[exception name] hasPrefix:
@"Oolite"])
7340 [
self handleOoliteException:exception];
7345 if (update_stage_param !=
nil) update_stage = [NSString stringWithFormat:update_stage, update_stage_param];
7347 OOLog(
kOOLogException,
@"***** Exception during [%@] in [Universe update:] : %@ : %@ *****", update_stage, [exception name], [exception reason]);
7353 update_stage =
@"clean up";
7354 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7355 for (i = 0; i < ent_count; i++)
7357 [my_entities[i] release];
7367 update_stage =
@"JS Garbage Collection";
7368 OOLog(
@"universe.profile.update",
@"%@", update_stage);
7371 uint32 gcbytes1 = JS_GetGCParameter(JS_GetRuntime(context),JSGC_BYTES);
7377 uint32 gcbytes2 = JS_GetGCParameter(JS_GetRuntime(context),JSGC_BYTES);
7379 if (gcbytes2 < gcbytes1)
7381 OOLog(
@"universe.profile.jsgc",
@"Unplanned JS Garbage Collection from %d to %d",gcbytes1,gcbytes2);
7390 if ([
PLAYER status] == STATUS_DEAD) [PLAYER update:delta_t];
7393 [entitiesDeadThisUpdate autorelease];
7394 entitiesDeadThisUpdate =
nil;
7395 entitiesDeadThisUpdate = [[NSMutableSet alloc] initWithCapacity:n_entities];
7398 [
self prunePreloadingPlanetMaterials];
7401 OOLog(
@"universe.profile.update",
@"%@",
@"Update complete");
7406- (double) timeAccelerationFactor
7408 return timeAccelerationFactor;
7412- (void) setTimeAccelerationFactor:(
double)newTimeAccelerationFactor
7418 timeAccelerationFactor = newTimeAccelerationFactor;
7421- (double) timeAccelerationFactor
7427- (void) setTimeAccelerationFactor:(
double)newTimeAccelerationFactor
7433- (BOOL) ECMVisualFXEnabled
7435 return ECMVisualFXEnabled;
7439- (void) setECMVisualFXEnabled:(BOOL)isEnabled
7441 ECMVisualFXEnabled = isEnabled;
7445- (void) filterSortedLists
7455 Entity *e0, *next, *prev;
7456 OOHPScalar start, finish, next_start, next_finish, prev_start, prev_finish;
7479 start = e0->
position.z - 2.0f * e0->collision_radius;
7480 finish = start + 4.0f * e0->collision_radius;
7486 next_start = next->
position.z - 2.0f * next->collision_radius;
7487 if (next_start < finish)
7490 while ((next)&&(next_start < finish))
7493 next_finish = next_start + 4.0f * next->collision_radius;
7494 if (next_finish > finish)
7495 finish = next_finish;
7501 next_start = next->
position.z - 2.0f * next->collision_radius;
7523 start = e0->
position.z + 2.0f * e0->collision_radius;
7524 finish = start - 4.0f * e0->collision_radius;
7530 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7531 if (prev_start > finish)
7534 while ((prev)&&(prev_start > finish))
7537 prev_finish = prev_start - 4.0f * prev->collision_radius;
7538 if (prev_finish < finish)
7539 finish = prev_finish;
7545 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7569 start = e0->
position.y - 2.0f * e0->collision_radius;
7570 finish = start + 4.0f * e0->collision_radius;
7577 next_start = next->
position.y - 2.0f * next->collision_radius;
7578 if (next_start < finish)
7581 while ((next)&&(next_start < finish))
7584 next_finish = next_start + 4.0f * next->collision_radius;
7585 if (next_finish > finish)
7586 finish = next_finish;
7592 next_start = next->
position.y - 2.0f * next->collision_radius;
7614 start = e0->
position.y + 2.0f * e0->collision_radius;
7615 finish = start - 4.0f * e0->collision_radius;
7621 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7622 if (prev_start > finish)
7625 while ((prev)&&(prev_start > finish))
7628 prev_finish = prev_start - 4.0f * prev->collision_radius;
7629 if (prev_finish < finish)
7630 finish = prev_finish;
7636 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7660 start = e0->
position.x - 2.0f * e0->collision_radius;
7661 finish = start + 4.0f * e0->collision_radius;
7667 next_start = next->
position.x - 2.0f * next->collision_radius;
7668 if (next_start < finish)
7671 while ((next)&&(next_start < finish))
7674 next_finish = next_start + 4.0f * next->collision_radius;
7675 if (next_finish > finish)
7676 finish = next_finish;
7682 next_start = next->
position.x - 2.0f * next->collision_radius;
7704 start = e0->
position.x + 2.0f * e0->collision_radius;
7705 finish = start - 4.0f * e0->collision_radius;
7711 prev_start = prev->
position.x + 2.0f * prev->collision_radius;
7712 if (prev_start > finish)
7715 while ((prev)&&(prev_start > finish))
7718 prev_finish = prev_start - 4.0f * prev->collision_radius;
7719 if (prev_finish < finish)
7720 finish = prev_finish;
7726 prev_start = prev->
position.x + 2.0f * prev->collision_radius;
7750 start = e0->
position.y - 2.0f * e0->collision_radius;
7751 finish = start + 4.0f * e0->collision_radius;
7757 next_start = next->
position.y - 2.0f * next->collision_radius;
7758 if (next_start < finish)
7761 while ((next)&&(next_start < finish))
7764 next_finish = next_start + 4.0f * next->collision_radius;
7765 if (next_finish > finish)
7766 finish = next_finish;
7772 next_start = next->
position.y - 2.0f * next->collision_radius;
7793 start = e0->
position.y + 2.0f * e0->collision_radius;
7794 finish = start - 4.0f * e0->collision_radius;
7800 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7801 if (prev_start > finish)
7804 while ((prev)&&(prev_start > finish))
7807 prev_finish = prev_start - 4.0f * prev->collision_radius;
7808 if (prev_finish < finish)
7809 finish = prev_finish;
7815 prev_start = prev->
position.y + 2.0f * prev->collision_radius;
7839 start = e0->
position.z - 2.0f * e0->collision_radius;
7840 finish = start + 4.0f * e0->collision_radius;
7846 next_start = next->
position.z - 2.0f * next->collision_radius;
7847 if (next_start < finish)
7850 while ((next)&&(next_start < finish))
7855 next_finish = next_start + 4.0f * next->collision_radius;
7856 if (next_finish > finish)
7857 finish = next_finish;
7863 next_start = next->
position.z - 2.0f * next->collision_radius;
7885 start = e0->
position.z + 2.0f * e0->collision_radius;
7886 finish = start - 4.0f * e0->collision_radius;
7892 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7893 if (prev_start > finish)
7896 while ((prev)&&(prev_start > finish))
7921 OOLog(
@"general.error.inconsistentState",
@"Unexpected state in collision chain builder prev=%@, prev->c=%@, e0=%@, e0->c=%@",prev,prev->
collision_chain,e0,e0->
collision_chain);
7926 prev_finish = prev_start - 4.0f * prev->collision_radius;
7927 if (prev_finish < finish)
7928 finish = prev_finish;
7934 prev_start = prev->
position.z + 2.0f * prev->collision_radius;
7960 [
self setGalaxyTo:g andReinit:NO];
7964- (void) setGalaxyTo:(
OOGalaxyID) g andReinit:(BOOL) forced
7967 NSAutoreleasePool *pool =
nil;
7969 if (galaxyID != g || forced) {
7973 pool = [[NSAutoreleasePool alloc] init];
7975 for (i = 0; i < 256; i++)
7977 if (system_names[i])
7979 [system_names[i] release];
7981 system_names[i] = [[systemManager getProperty:@"name" forSystem:i inGalaxy:g] retain];
7991 NSDictionary *systemData;
7994 NSString *scriptName;
8001 systemData = [
self generateSystemData:targetSystemID];
8002 economy = [systemData oo_unsignedCharForKey:KEY_ECONOMY];
8003 scriptName = [systemData oo_stringForKey:@"market_script" defaultValue:nil];
8006 commodityMarket = [[commodities generateMarketForSystemWithEconomy:economy andScript:scriptName] retain];
8016- (NSDictionary *) descriptions
8018 if (_descriptions ==
nil)
8023 stringByAppendingPathComponent:@"Config"]
8024 stringByAppendingPathComponent:@"descriptions.plist"]];
8026 [
self verifyDescriptions];
8028 return _descriptions;
8032static void VerifyDesc(NSString *key,
id desc);
8037 if ([desc rangeOfString:
@"%n"].location != NSNotFound)
8039 OOLog(
@"descriptions.verify.percentN",
@"***** FATAL: descriptions.plist entry \"%@\
" contains the dangerous control sequence %%n.", key);
8048 foreach (subDesc, desc)
8050 VerifyDesc(key, subDesc);
8055static void VerifyDesc(NSString *key,
id desc)
8057 if ([desc isKindOfClass:[NSString class]])
8059 VerifyDescString(key, desc);
8061 else if ([desc isKindOfClass:[NSArray class]])
8063 VerifyDescArray(key, desc);
8065 else if ([desc isKindOfClass:[NSNumber class]])
8071 OOLogERR(
@"descriptions.verify.badType",
@"***** FATAL: descriptions.plist entry for \"%@\
" is neither a string nor an array.", key);
8089 NSString *key =
nil;
8090 if (_descriptions ==
nil)
8092 OOLog(
@"descriptions.verify",
@"%@",
@"***** FATAL: Tried to verify descriptions, but descriptions was nil - unable to load any descriptions.plist file.");
8097 VerifyDesc(key, [_descriptions objectForKey:key]);
8104 [_descriptions autorelease];
8106 [
self verifyDescriptions];
8110- (NSDictionary *) explosionSetting:(NSString *)explosion
8112 return [explosionSettings oo_dictionaryForKey:explosion defaultValue:nil];
8116- (NSArray *) scenarios
8124 [_scenarios autorelease];
8129- (NSDictionary *) characters
8135- (NSDictionary *) missiontext
8141- (NSString *)descriptionForKey:(NSString *)key
8143 return [
self chooseStringForKey:key inDictionary:[
self descriptions]];
8147- (NSString *)descriptionForArrayKey:(NSString *)key index:(
unsigned)index
8149 NSArray *array = [[
self descriptions] oo_arrayForKey:key];
8150 if ([array
count] <= index)
return nil;
8151 return [array objectAtIndex:index];
8155- (BOOL) descriptionBooleanForKey:(NSString *)key
8157 return [[
self descriptions] oo_boolForKey:key];
8163 return systemManager;
8169 return [NSString stringWithFormat:@"%d %d", g, s];
8175 return [NSString stringWithFormat:@"interstellar: %d %d %d", g, s1, s2];
8179- (NSDictionary *) generateSystemData:(
OOSystemID) s
8181 return [
self generateSystemData:s useCache:YES];
8186- (NSDictionary *) generateSystemData:(
OOSystemID) s useCache:(BOOL) useCache
8193 NSString *systemKey = [NSString stringWithFormat:@"%u %u",[PLAYER galaxyNumber],s];
8195 return [systemManager getPropertiesForSystemKey:systemKey];
8201- (NSDictionary *) currentSystemData
8205 if (![
self inInterstellarSpace])
8207 return [
self generateSystemData:systemID];
8211 static NSDictionary *interstellarDict =
nil;
8212 if (interstellarDict ==
nil)
8214 NSString *interstellarName =
DESC(
@"interstellar-space");
8215 NSString *notApplicable =
DESC(
@"not-applicable");
8216 NSNumber *minusOne = [NSNumber numberWithInt:-1];
8217 NSNumber *zero = [NSNumber numberWithInt:0];
8218 interstellarDict = [[NSDictionary alloc] initWithObjectsAndKeys:
8219 interstellarName, KEY_NAME,
8220 minusOne, KEY_GOVERNMENT,
8221 minusOne, KEY_ECONOMY,
8222 minusOne, KEY_TECHLEVEL,
8223 zero, KEY_POPULATION,
8224 zero, KEY_PRODUCTIVITY,
8226 notApplicable, KEY_INHABITANTS,
8227 notApplicable, KEY_DESCRIPTION,
8231 return interstellarDict;
8238- (BOOL) inInterstellarSpace
8240 return [
self sun] ==
nil;
8248- (void) setSystemDataKey:(NSString *)key value:(NSObject *)object fromManifest:(NSString *)manifest
8250 [
self setSystemDataForGalaxy:galaxyID planet:systemID key:key value:object fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
8254- (void) setSystemDataForGalaxy:(
OOGalaxyID)gnum planet:(
OOSystemID)pnum key:(NSString *)key value:(
id)object fromManifest:(NSString *)manifest forLayer:(
OOSystemLayer)layer
8256 static BOOL sysdataLocked = NO;
8259 OOLogERR(
@"script.error",
@"%@",
@"System properties cannot be set during 'systemInformationChanged' events to avoid infinite loops.");
8263 BOOL sameGalaxy = (gnum == [PLAYER currentGalaxyID]);
8264 BOOL sameSystem = (sameGalaxy && pnum == [
self currentSystemID]);
8267 if ([key isEqualToString:
KEY_RADIUS] && sameGalaxy && sameSystem)
8269 OOLogERR(
@"script.error",
@"System property '%@' cannot be set while in the system.",key);
8273 if ([key isEqualToString:
@"coordinates"])
8275 OOLogERR(
@"script.error",
@"System property '%@' cannot be set.",key);
8280 NSString *overrideKey = [NSString stringWithFormat:@"%u %u", gnum, pnum];
8281 NSDictionary *sysInfo =
nil;
8284 [gui refreshStarChart];
8286 if (
object !=
nil) {
8288 if ([key isEqualToString:
KEY_NAME])
8290 object=(id)[[(NSString *)
object lowercaseString] capitalizedString];
8293 if (system_names[pnum]) [system_names[pnum] release];
8294 system_names[pnum] = [(NSString *)object retain];
8297 else if ([key isEqualToString:
@"sun_radius"])
8299 if ([
object doubleValue] < 1000.0 || [
object doubleValue] > 10000000.0 )
8301 object = ([object doubleValue] < 1000.0 ? (id)
@"1000.0" : (id)
@"10000000.0");
8304 else if ([key hasPrefix:
@"corona_"])
8306 object = (id)[NSString stringWithFormat:
@"%f",OOClamp_0_1_f([object floatValue])];
8310 [systemManager setProperty:key forSystemKey:overrideKey andLayer:layer toValue:object fromManifest:manifest];
8316 sysInfo = [systemManager getPropertiesForCurrentSystem];
8326 [[
self station] setEquivalentTechLevel:[object intValue]];
8327 [[
self station] setLocalShipyard:[
self shipsForSaleForSystem:systemID
8328 withTL:[object intValue] atTime:[PLAYER clockTime]]];
8331 else if ([key isEqualToString:
@"sun_color"] || [key isEqualToString:
@"star_count_multiplier"] ||
8332 [key isEqualToString:
@"nebula_count_multiplier"] || [key hasPrefix:
@"sky_"])
8337 for (i = n_entities - 1; i > 0; i--)
8338 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[SkyEntity class]]))
8339 the_sky = (
SkyEntity*)sortedEntities[i];
8345 if ([key isEqualToString:
@"sun_color"])
8354 for (i = n_entities - 1; i > 0; i--)
8355 if ((sortedEntities[i]) && ([sortedEntities[i] isKindOfClass:[DustEntity class]]))
8356 [(
DustEntity*)sortedEntities[i] setDustColor:[color blendedColorWithFraction:0.5 ofColor:[OOColor whiteColor]]];
8360 else if (the_sun !=
nil && ([key hasPrefix:
@"sun_"] || [key hasPrefix:
@"corona_"]))
8364 else if ([key isEqualToString:
@"texture"])
8366 [[
self planet] setUpPlanetFromTexture:(NSString *)object];
8368 else if ([key isEqualToString:
@"texture_hsb_color"])
8370 [[
self planet] setUpPlanetFromTexture: [[
self planet] textureFileName]];
8372 else if ([key isEqualToString:
@"air_color"])
8376 else if ([key isEqualToString:
@"illumination_color"])
8380 else if ([key isEqualToString:
@"air_color_mix_ratio"])
8382 [[
self planet] setAirColorMixRatio:[sysInfo oo_floatForKey:key]];
8386 sysdataLocked = YES;
8387 [PLAYER doScriptEvent:OOJSID("systemInformationChanged") withArguments:[NSArray arrayWithObjects:[NSNumber numberWithInt:gnum],[NSNumber numberWithInt:pnum],key,object,nil]];
8395 NSString *systemKey = [
self keyForPlanetOverridesForSystem:pnum inGalaxy:gnum];
8396 return [systemManager getPropertiesForSystemKey:systemKey];
8402 return [[
self generateSystemDataForGalaxy:gnum planet:pnum] allKeys];
8409 return [systemManager getProperty:key forSystem:pnum inGalaxy:gnum];
8415 return [
self getSystemName:sys forGalaxy:galaxyID];
8421 return [systemManager getProperty:@"name" forSystem:sys inGalaxy:gnum];
8427 return [[systemManager getProperty:@"government" forSystem:sys inGalaxy:galaxyID] unsignedCharValue];
8431- (NSString *) getSystemInhabitants:(
OOSystemID) sys
8433 return [
self getSystemInhabitants:sys plural:YES];
8437- (NSString *) getSystemInhabitants:(
OOSystemID) sys plural:(BOOL)plural
8439 NSString *ret =
nil;
8442 ret = [systemManager getProperty:KEY_INHABITANT forSystem:sys inGalaxy:galaxyID];
8450 return [systemManager getProperty:KEY_INHABITANTS forSystem:sys inGalaxy:galaxyID];
8455- (NSPoint) coordinatesForSystem:(
OOSystemID)s
8457 return [systemManager getCoordinatesForSystem:s inGalaxy:galaxyID];
8461- (
OOSystemID) findSystemFromName:(NSString *) sysName
8463 if (sysName ==
nil)
return -1;
8465 NSString *system_name =
nil;
8466 NSString *match = [sysName lowercaseString];
8468 for (i = 0; i < 256; i++)
8470 system_name = [system_names[i] lowercaseString];
8471 if ([system_name isEqualToString:match])
8482 OOLog(
@"deprecated.function",
@"%@",
@"findSystemAtCoords");
8483 return [
self findSystemNumberAtCoords:coords withGalaxy:g includingHidden:YES];
8487- (NSMutableArray *) nearbyDestinationsWithinRange:(
double)range
8489 NSMutableArray *result = [NSMutableArray arrayWithCapacity:16];
8492 NSPoint here = [PLAYER galaxy_coordinates];
8494 for (
unsigned short i = 0; i < 256; i++)
8496 NSPoint there = [
self coordinatesForSystem:i];
8498 if (dist <= range && (i != systemID || [
self inInterstellarSpace]))
8500 [result addObject: [NSDictionary dictionaryWithObjectsAndKeys:
8501 [NSNumber numberWithDouble:dist], @"distance",
8502 [NSNumber numberWithInt:i], @"sysID",
8503 [[
self generateSystemData:i] oo_stringForKey:@"sun_gone_nova" defaultValue:@"0"], @"nova",
8517 double min_dist = 10000.0;
8520 BOOL connected[256];
8521 for (i = 0; i < 256; i++)
8524 for (n = 0; n < 3; n++)
8526 for (i = 0; i < 256; i++)
8528 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8529 for (j = 0; j < 256; j++)
8531 NSPoint jpos = [systemManager getCoordinatesForSystem:j inGalaxy:g];
8535 connected[j] |= connected[i];
8536 connected[i] |= connected[j];
8542 for (i = 0; i < 256; i++)
8544 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8546 if ((connected[i])&&(distance < min_dist)&&(distance != 0.0))
8548 min_dist = distance;
8564 double min_dist = 10000.0;
8567 BOOL connected[256];
8568 for (i = 0; i < 256; i++)
8571 for (n = 0; n < 3; n++)
8573 for (i = 0; i < 256; i++)
8575 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8576 for (j = 0; j < 256; j++)
8578 NSPoint jpos = [systemManager getCoordinatesForSystem:j inGalaxy:g];
8582 connected[j] |= connected[i];
8583 connected[i] |= connected[j];
8589 for (i = 0; i < 256; i++)
8591 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8593 if ((connected[i])&&(distance < min_dist))
8595 min_dist = distance;
8604- (
OOSystemID) findSystemNumberAtCoords:(NSPoint) coords withGalaxy:(
OOGalaxyID)g includingHidden:(BOOL)hidden
8613 unsigned distance, dx, dy;
8615 unsigned min_dist = 10000;
8617 for (i = 0; i < 256; i++)
8620 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:g];
8621 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8627 NSPoint ipos = [systemManager getCoordinatesForSystem:i inGalaxy:g];
8628 dx =
ABS(coords.x - ipos.x);
8629 dy =
ABS(coords.y - ipos.y);
8631 if (dx > dy) distance = (dx + dx + dy) / 2;
8632 else distance = (dx + dy + dy) / 2;
8634 if (distance < min_dist)
8636 min_dist = distance;
8640 if ((distance == min_dist)&&(coords.y > ipos.y))
8645 else if ((distance == min_dist)&&(coords.y == ipos.y)&&(i==[
PLAYER targetSystemID]))
8654- (NSPoint) findSystemCoordinatesWithPrefix:(NSString *) p_fix
8656 return [
self findSystemCoordinatesWithPrefix:p_fix exactMatch:NO];
8660- (NSPoint) findSystemCoordinatesWithPrefix:(NSString *) p_fix exactMatch:(BOOL) exactMatch
8662 NSString *system_name =
nil;
8663 NSPoint system_coords = NSMakePoint(-1.0,-1.0);
8666 for (i = 0; i < 256; i++)
8668 system_found[i] = NO;
8669 system_name = [system_names[i] lowercaseString];
8670 if ((exactMatch && [system_name isEqualToString:p_fix]) || (!exactMatch && [system_name hasPrefix:p_fix]))
8673 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxyID];
8674 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8680 system_found[i] = YES;
8683 system_coords = [systemManager getCoordinatesForSystem:i inGalaxy:galaxyID];
8688 return system_coords;
8692- (BOOL*) systemsFound
8694 return (BOOL*)system_found;
8698- (NSString*)systemNameIndex:(
OOSystemID)index
8700 return system_names[index & 255];
8717 if (start == -1 || goal == -1)
return nil;
8719#ifdef CACHE_ROUTE_FROM_SYSTEM_RESULTS
8721 static NSDictionary *c_route =
nil;
8725 if (c_route !=
nil && c_start == start && c_goal == goal && c_optimizeBy == optimizeBy)
8734 if (start > 255 || goal > 255)
return nil;
8736 NSArray *neighbours[256];
8737 BOOL concealed[256];
8738 for (i = 0; i < 256; i++)
8740 NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxyID];
8741 NSInteger concealment = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
8744 neighbours[i] = [NSArray array];
8749 neighbours[i] = [
self neighboursToSystem:i];
8756 double maxCost = optimizeBy ==
OPTIMIZED_BY_TIME ? 256 * (7 * 7) : 256 * (7 * 256 + 7);
8758 NSMutableArray *curr = [NSMutableArray arrayWithCapacity:256];
8761 NSMutableArray *next = [NSMutableArray arrayWithCapacity:256];
8762 while ([curr
count] != 0)
8764 for (i = 0; i < [curr count]; i++) {
8766 NSArray *ns = neighbours[[elemI
location]];
8767 for (j = 0; j < [ns count]; j++)
8777 NSPoint cpos = [systemManager getCoordinatesForSystem:c inGalaxy:galaxyID];
8778 NSPoint npos = [systemManager getCoordinatesForSystem:n inGalaxy:galaxyID];
8781 double lastTime = lastDistance * lastDistance;
8783 double distance = [ce
distance] + lastDistance;
8784 double time = [ce
time] + lastTime;
8786 int jumps = [ce
jumps] + 1;
8788 if (cost < maxCost && (cheapest[n] ==
nil || [cheapest[n] cost] > cost)) {
8793 if (n == goal && cost < maxCost)
8798 [curr setArray:next];
8799 [next removeAllObjects];
8803 if (!cheapest[goal])
return nil;
8805 NSMutableArray *route = [NSMutableArray arrayWithCapacity:256];
8809 [route insertObject:[NSNumber numberWithInt:[e
location]] atIndex:0];
8810 if ([e parent] == -1)
break;
8811 e = cheapest[[e
parent]];
8814#ifdef CACHE_ROUTE_FROM_SYSTEM_RESULTS
8817 c_optimizeBy = optimizeBy;
8819 c_route = [[NSDictionary alloc] initWithObjectsAndKeys: route, @"route", [NSNumber numberWithDouble:[cheapest[goal]
distance]], @"distance", nil];
8823 return [NSDictionary dictionaryWithObjectsAndKeys:
8825 [NSNumber numberWithDouble:[cheapest[goal]
distance]], @"distance",
8826 [NSNumber numberWithDouble:[cheapest[goal]
time]], @"time",
8827 [NSNumber numberWithInt:[cheapest[goal]
jumps]], @"jumps",
8833- (NSArray *) neighboursToSystem: (
OOSystemID) s
8835 if (s == systemID && closeSystems !=
nil)
8837 return closeSystems;
8839 NSArray *neighbours = [systemManager getNeighbourIDsForSystem:s inGalaxy:galaxyID];
8843 [closeSystems release];
8844 closeSystems = [neighbours copy];
8845 return closeSystems;
8879- (void) preloadPlanetTexturesForSystem:(
OOSystemID)s
8883 [
self prunePreloadingPlanetMaterials];
8885 if ([_preloadingPlanetMaterials
count] < 3)
8887 if (_preloadingPlanetMaterials ==
nil) _preloadingPlanetMaterials = [[NSMutableArray alloc] initWithCapacity:4];
8895 if (![surface isFinishedLoading])
8897 [_preloadingPlanetMaterials addObject:surface];
8902 if (atmo !=
nil) [_preloadingPlanetMaterials addObject:atmo];
8912- (NSDictionary *) globalSettings
8914 return globalSettings;
8918- (NSArray *) equipmentData
8920 return equipmentData;
8924- (NSArray *) equipmentDataOutfitting
8926 return equipmentDataOutfitting;
8932 return commodityMarket;
8936- (NSString *) timeDescription:(
double) interval
8938 double r_time = interval;
8939 NSString* result =
@"";
8943 int days = floor(r_time / 86400);
8944 r_time -= 86400 * days;
8945 result = [NSString stringWithFormat:@"%@ %d day%@", result, days, (days > 1) ? @"s" : @""];
8949 int hours = floor(r_time / 3600);
8950 r_time -= 3600 * hours;
8951 result = [NSString stringWithFormat:@"%@ %d hour%@", result, hours, (hours > 1) ? @"s" : @""];
8955 int mins = floor(r_time / 60);
8956 r_time -= 60 * mins;
8957 result = [NSString stringWithFormat:@"%@ %d minute%@", result, mins, (mins > 1) ? @"s" : @""];
8961 int secs = floor(r_time);
8962 result = [NSString stringWithFormat:@"%@ %d second%@", result, secs, (secs > 1) ? @"s" : @""];
8964 return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
8968- (NSString *) shortTimeDescription:(
double) interval
8970 double r_time = interval;
8971 NSString* result =
@"";
8974 if (interval <= 0.0)
8975 return DESC(
@"contracts-no-time");
8979 int days = floor(r_time / 86400);
8980 r_time -= 86400 * days;
8981 result = [NSString stringWithFormat:@"%@ %d %@", result, days, DESC_PLURAL(@"contracts-day-word", days)];
8986 int hours = floor(r_time / 3600);
8987 r_time -= 3600 * hours;
8988 result = [NSString stringWithFormat:@"%@ %d %@", result, hours, DESC_PLURAL(@"contracts-hour-word", hours)];
8991 if (parts < 2 && r_time > 60)
8993 int mins = floor(r_time / 60);
8994 r_time -= 60 * mins;
8995 result = [NSString stringWithFormat:@"%@ %d %@", result, mins, DESC_PLURAL(@"contracts-minute-word", mins)];
8998 if (parts < 2 && r_time > 0)
9000 int secs = floor(r_time);
9001 result = [NSString stringWithFormat:@"%@ %d %@", result, secs, DESC_PLURAL(@"contracts-second-word", secs)];
9003 return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
9007- (void) makeSunSkimmer:(
ShipEntity *) ship andSetAI:(BOOL)setAI
9009 if (setAI) [ship
switchAITo:@"oolite-traderAI.js"];
9013 if ([ship heatInsulation] < minInsulation) [ship
setHeatInsulation:minInsulation];
9019 Random_Seed ret = [systemManager getRandomSeedForCurrentSystem];
9035- (void) loadStationMarkets:(NSArray *)marketData
9037 if (marketData ==
nil)
9042 NSArray *stations = [
self stations];
9044 NSDictionary *savedMarket =
nil;
9046 foreach (savedMarket, marketData)
9048 HPVector pos = [savedMarket oo_hpvectorForKey:@"position"];
9049 foreach (station, stations)
9052 if ([station allowsSaving] && station != [
UNIVERSE station])
9055 if (HPdistance2(pos,[station position]) < 1000000)
9057 [station setLocalMarket:[savedMarket oo_arrayForKey:@"market"]];
9067- (NSArray *) getStationMarkets
9069 NSMutableArray *markets = [[NSMutableArray alloc] init];
9070 NSArray *stations = [
self stations];
9073 NSMutableDictionary *savedMarket =
nil;
9077 foreach (station, stations)
9080 if ([station allowsSaving] && station != [
UNIVERSE station])
9082 stationMarket = [station localMarket];
9083 if (stationMarket !=
nil)
9085 savedMarket = [NSMutableDictionary dictionaryWithCapacity:2];
9087 [savedMarket setObject:ArrayFromHPVector([station position]) forKey:@"position"];
9088 [markets addObject:savedMarket];
9093 return [markets autorelease];
9102 NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionary];
9104 float tech_price_boost = (ship_seed.
a + ship_seed.b) / 256.0;
9110 for (i = 0; i < 256; i++)
9112 long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
9114 long long c_time = ship_seed.
a * 0x10000 + ship_seed.b * 0x100 + ship_seed.c;
9115 double ship_sold_time = reference_time + c_time;
9117 if (ship_sold_time < 0)
9118 ship_sold_time += 0x1000000;
9120 double days_until_sale = (ship_sold_time - current_time) / 86400.0;
9122 NSMutableArray *keysForShips = [NSMutableArray arrayWithArray:[registry
playerShipKeys]];
9124 for (si = 0; si < [keysForShips count]; si++)
9127 NSString *key = [keysForShips oo_stringAtIndex:si];
9129 NSArray *conditions = [dict oo_arrayForKey:@"conditions"];
9131 if (![player scriptTestConditions:conditions])
9133 [keysForShips removeObjectAtIndex:si--];
9135 NSString *condition_script = [dict oo_stringForKey:@"condition_script"];
9136 if (condition_script !=
nil)
9138 OOJSScript *condScript = [
self getConditionScript:condition_script];
9139 if (condScript !=
nil)
9143 JSBool allow_purchase;
9147 OK = [condScript
callMethod:OOJSID("allowOfferShip")
9152 if (OK) OK = JS_ValueToBoolean(context, result, &allow_purchase);
9156 if (OK && !allow_purchase)
9161 [keysForShips removeObjectAtIndex:si--];
9168 NSDictionary *systemInfo = [
self generateSystemData:s];
9170 if (specialTL != NSNotFound)
9173 techlevel = specialTL;
9178 techlevel = [systemInfo oo_unsignedIntForKey:KEY_TECHLEVEL];
9180 unsigned ship_index = (ship_seed.
d * 0x100 + ship_seed.e) % [keysForShips
count];
9181 NSString *ship_key = [keysForShips oo_stringAtIndex:ship_index];
9183 OOTechLevelID ship_techlevel = [ship_info oo_intForKey:KEY_TECHLEVEL];
9185 double chance = 1.0 - pow(1.0 - [ship_info oo_doubleForKey:KEY_CHANCE], MAX((
OOTechLevelID)1, techlevel - ship_techlevel));
9188 int superRand1 = ship_seed.
a * 0x10000 + ship_seed.c * 0x100 + ship_seed.e;
9189 uint32_t superRand2 = ship_seed.
b * 0x10000 + ship_seed.d * 0x100 + ship_seed.f;
9194 if ((days_until_sale > 0.0) && (days_until_sale < 30.0) && (ship_techlevel <= techlevel) && (
randf() < chance) && (shipBaseDict !=
nil))
9196 NSMutableDictionary* shipDict = [NSMutableDictionary dictionaryWithDictionary:shipBaseDict];
9197 NSMutableString* shortShipDescription = [NSMutableString stringWithCapacity:256];
9198 NSString *shipName = [shipDict oo_stringForKey:@"display_name" defaultValue:[shipDict oo_stringForKey:KEY_NAME]];
9201 NSMutableArray* extras = [NSMutableArray arrayWithArray:[[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
9202 NSString* fwdWeaponString = [[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9203 NSString* aftWeaponString = [[ship_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON];
9205 NSMutableArray* options = [NSMutableArray arrayWithArray:[ship_info oo_arrayForKey:KEY_OPTIONAL_EQUIPMENT]];
9206 OOCargoQuantity maxCargo = [shipDict oo_unsignedIntForKey:@"max_cargo"];
9212 [shortShipDescription appendFormat:@"%@:", shipName];
9220 if (fwdWeapon && fwdWeaponString) [shipDict setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9221 if (aftWeapon && aftWeaponString) [shipDict setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
9223 int passengerBerthCount = 0;
9224 BOOL customised = NO;
9225 BOOL weaponCustomized = NO;
9227 NSString *fwdWeaponDesc =
nil;
9229 NSString *shortExtrasKey =
@"shipyard-first-extra";
9234 while ((
randf() < chance) && ([options
count]))
9237 int optionIndex =
Ranrot() % [options count];
9238 NSString *equipmentKey = [options oo_stringAtIndex:optionIndex];
9245 NSString *eqShortDesc = [item
name];
9247 if ([item techLevel] > techlevel)
9250 eqTechLevel =
MIN(eqTechLevel, 15U);
9253 if (
randf() * (eqTechLevel - techlevel) < 1.0)
9256 eqPrice *= (tech_price_boost + eqTechLevel - techlevel) * 90 / 100;
9262 if ([item incompatibleEquipment] !=
nil && extras !=
nil)
9265 BOOL incompatible = NO;
9267 foreach (key, [item incompatibleEquipment])
9269 if ([extras containsObject:key])
9271 [options removeObject:equipmentKey];
9276 if (incompatible)
break;
9279 foreach (key, [item incompatibleEquipment])
9281 if ([options containsObject:key])
9283 [options removeObject:key];
9290 if (condition_script !=
nil)
9292 OOJSScript *condScript = [
self getConditionScript:condition_script];
9293 if (condScript !=
nil)
9297 JSBool allow_addition;
9301 OK = [condScript
callMethod:OOJSID("allowAwardEquipment")
9306 if (OK) OK = JS_ValueToBoolean(JScontext, result, &allow_addition);
9310 if (OK && !allow_addition)
9321 if ([item requiresEquipment] !=
nil && extras !=
nil)
9326 foreach (key, [item requiresEquipment])
9328 if (![extras containsObject:key])
9336 if ([item requiresAnyEquipment] !=
nil && extras !=
nil)
9341 foreach (key, [item requiresAnyEquipment])
9343 if ([extras containsObject:key])
9353 if ([equipmentKey isEqualTo:
@"EQ_NAVAL_ENERGY_UNIT"])
9355 if ([extras containsObject:
@"EQ_ENERGY_UNIT"])
9357 [options removeObject:equipmentKey];
9362 if ([equipmentKey hasPrefix:
@"EQ_WEAPON"])
9366 if (availableFacings &
WEAPON_FACING_FORWARD && [new_weapon weaponThreatAssessment] > [fwdWeapon weaponThreatAssessment])
9369 price -= [
self getEquipmentPriceForKey:fwdWeaponString] * 90 / 1000;
9371 fwdWeaponString = equipmentKey;
9372 fwdWeapon = new_weapon;
9373 [shipDict setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9374 weaponCustomized = YES;
9375 fwdWeaponDesc = eqShortDesc;
9380 if (availableFacings &
WEAPON_FACING_AFT && (
isWeaponNone(aftWeapon) || [new_weapon weaponThreatAssessment] > [aftWeapon weaponThreatAssessment]))
9382 price -= [
self getEquipmentPriceForKey:aftWeaponString] * 90 / 1000;
9384 aftWeaponString = equipmentKey;
9385 aftWeapon = new_weapon;
9386 [shipDict setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
9390 [options removeObject:equipmentKey];
9397 if ([equipmentKey isEqualToString:
@"EQ_PASSENGER_BERTH"])
9403 [extras addObject:equipmentKey];
9404 passengerBerthCount++;
9410 [options removeObject:equipmentKey];
9416 [extras addObject:equipmentKey];
9417 if ([item isVisible])
9419 NSString *item = eqShortDesc;
9420 [shortShipDescription appendString:OOExpandKey(shortExtrasKey, item)];
9421 shortExtrasKey =
@"shipyard-additional-extra";
9424 [options removeObject:equipmentKey];
9430 [options removeObject:equipmentKey];
9435 BOOL lowercaseIgnore = [[
self descriptions] oo_boolForKey:@"lowercase_ignore"];
9437 if (passengerBerthCount)
9439 NSString* npb = (passengerBerthCount > 1)? [NSString stringWithFormat:
@"%d ", passengerBerthCount] : (id)
@"";
9440 NSString* ppb =
DESC_PLURAL(
@"passenger-berth", passengerBerthCount);
9441 NSString* extraPassengerBerthsDescription = [NSString stringWithFormat:DESC(@"extra-@-@-(passenger-berths)"), npb, ppb];
9442 NSString *item = extraPassengerBerthsDescription;
9443 [shortShipDescription appendString:OOExpandKey(shortExtrasKey, item)];
9444 shortExtrasKey =
@"shipyard-additional-extra";
9449 [shortShipDescription appendString:OOExpandKey(@"shipyard-standard-customer-model")];
9452 if (weaponCustomized)
9454 NSString *weapon = (lowercaseIgnore ? fwdWeaponDesc : [fwdWeaponDesc lowercaseString]);
9455 [shortShipDescription appendString:OOExpandKey(@"shipyard-forward-weapon-upgraded", weapon)];
9457 if (price > base_price)
9459 price = base_price +
cunningFee(price - base_price, 0.05);
9462 [shortShipDescription appendString:OOExpandKey(@"shipyard-price", price)];
9464 NSString *shipID = [NSString stringWithFormat:@"%06x-%06x", superRand1, superRand2];
9468 NSDictionary *ship_info_dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
9469 shipID, SHIPYARD_KEY_ID,
9470 ship_key, SHIPYARD_KEY_SHIPDATA_KEY,
9471 shipDict, SHIPYARD_KEY_SHIP,
9472 shortShipDescription, KEY_SHORT_DESCRIPTION,
9473 [NSNumber numberWithUnsignedLongLong:price], SHIPYARD_KEY_PRICE,
9474 extras, KEY_EQUIPMENT_EXTRAS,
9475 [NSNumber numberWithUnsignedShort:personality], SHIPYARD_KEY_PERSONALITY,
9478 [resultDictionary setObject:ship_info_dictionary forKey:shipID];
9488 NSMutableArray *resultArray = [[[resultDictionary allValues] mutableCopy] autorelease];
9489 [resultArray sortUsingFunction:compareName context:NULL];
9494 while (i < [resultArray
count])
9496 if (
compareName([resultArray objectAtIndex:i - 1], [resultArray objectAtIndex:i],
nil) == NSOrderedSame )
9498 [resultArray removeObjectAtIndex: i];
9508 return [NSArray arrayWithArray:resultArray];
9514 NSDictionary *ship1 = [(NSDictionary *)dict1 oo_dictionaryForKey:SHIPYARD_KEY_SHIP];
9515 NSDictionary *ship2 = [(NSDictionary *)dict2 oo_dictionaryForKey:SHIPYARD_KEY_SHIP];
9516 NSString *name1 = [ship1 oo_stringForKey:KEY_NAME];
9517 NSString *name2 = [ship2 oo_stringForKey:KEY_NAME];
9519 NSComparisonResult result = [[name1 lowercaseString] compare:[name2 lowercaseString]];
9520 if (result != NSOrderedSame)
9529 NSNumber *price1 = [(NSDictionary *)dict1 objectForKey:SHIPYARD_KEY_PRICE];
9530 NSNumber *price2 = [(NSDictionary *)dict2 objectForKey:SHIPYARD_KEY_PRICE];
9532 return [price1 compare:price2];
9540 NSString *ship_desc = [dict oo_stringForKey:@"ship_desc"];
9544 if (shipyard_info ==
nil)
9546 OOLogERR(
@"universe.tradeInValueForCommanderDictionary.valueCalculationError",
9547 @"Shipyard dictionary entry for ship %@ required for trade in value calculation, but does not exist. Setting ship value to 0.", ship_desc);
9551 base_price = [shipyard_info oo_unsignedLongLongForKey:SHIPYARD_KEY_PRICE defaultValue:0ULL];
9554 if(base_price == 0ULL)
return base_price;
9562 unsigned ship_missiles = [dict oo_unsignedIntForKey:@"missiles"];
9563 unsigned ship_max_passengers = [dict oo_unsignedIntForKey:@"max_passengers"];
9564 NSMutableArray *ship_extra_equipment = [NSMutableArray arrayWithArray:[[dict oo_dictionaryForKey:@"extra_equipment"] allKeys]];
9566 NSDictionary *basic_info = [shipyard_info oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT];
9567 unsigned base_missiles = [basic_info oo_unsignedIntForKey:KEY_EQUIPMENT_MISSILES];
9568 OOCreditsQuantity base_missiles_value = base_missiles * [UNIVERSE getEquipmentPriceForKey:@"EQ_MISSILE"] / 10;
9569 NSString *base_weapon_key = [basic_info oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
9570 OOCreditsQuantity base_weapons_value = [UNIVERSE getEquipmentPriceForKey:base_weapon_key] / 10;
9571 NSMutableArray *base_extra_equipment = [NSMutableArray arrayWithArray:[basic_info oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
9572 NSString *weapon_key =
nil;
9575 base_weapon_key = [basic_info oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON defaultValue:nil];
9576 if (base_weapon_key !=
nil)
9577 base_weapons_value += [
UNIVERSE getEquipmentPriceForKey:base_weapon_key] / 10;
9584 NSArray *missileRoles = [dict oo_arrayForKey:@"missile_roles"];
9585 if (missileRoles !=
nil)
9588 for (i = 0; i < ship_missiles; i++)
9590 NSString *missile_desc = [missileRoles oo_stringAtIndex:i];
9591 if (missile_desc !=
nil && ![missile_desc isEqualToString:
@"NONE"])
9593 ship_missiles_value += [
UNIVERSE getEquipmentPriceForKey:missile_desc] / 10;
9598 ship_missiles_value = ship_missiles * [UNIVERSE getEquipmentPriceForKey:@"EQ_MISSILE"] / 10;
9601 long long extra_equipment_value = ship_max_passengers * [UNIVERSE getEquipmentPriceForKey:@"EQ_PASSENGER_BERTH"]/10;
9604 extra_equipment_value += ship_missiles_value - base_missiles_value;
9607 if (ship_fwd_weapon)
9610 ship_main_weapons_value = [UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9612 if (ship_aft_weapon)
9615 if (base_weapon_key !=
nil)
9617 ship_main_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9621 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9624 if (ship_port_weapon)
9627 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9629 if (ship_starboard_weapon)
9632 ship_other_weapons_value += [
UNIVERSE getEquipmentPriceForKey:weapon_key] / 10;
9636 extra_equipment_value += ship_other_weapons_value;
9637 extra_equipment_value += ship_main_weapons_value - base_weapons_value;
9640 NSString *eq_key =
nil;
9644 for (i = [base_extra_equipment
count]-1; i > 0;i--)
9646 eq_key = [base_extra_equipment oo_stringAtIndex:i];
9647 if ([base_extra_equipment indexOfObject:eq_key inRange:NSMakeRange(0, i-1)] != NSNotFound)
9648 [base_extra_equipment removeObjectAtIndex:i];
9652 for (i = [base_extra_equipment
count]-1; i >= 0; i--)
9654 eq_key = [base_extra_equipment oo_stringAtIndex:i];
9655 if ([ship_extra_equipment containsObject:eq_key])
9656 [ship_extra_equipment removeObject:eq_key];
9658 extra_equipment_value -= ([
UNIVERSE getEquipmentPriceForKey:eq_key] / 10);
9664 for (i = [ship_extra_equipment
count]-1; i >= 0; i--)
9666 eq_key = [ship_extra_equipment oo_stringAtIndex:i];
9668 if ([item isPortableBetweenShips]) [ship_extra_equipment removeObjectAtIndex:i];
9672 for (i = [ship_extra_equipment
count]-1; i >= 0; i--)
9673 extra_equipment_value += ([
UNIVERSE getEquipmentPriceForKey:[ship_extra_equipment oo_stringAtIndex:i]] / 10);
9676 extra_equipment_value *= extra_equipment_value < 0 ? 1.4 : 0.9;
9680 if ((
long long)scrap_value > (
long long)base_price + extra_equipment_value)
return scrap_value;
9682 return base_price + extra_equipment_value;
9686- (NSString *) brochureDescriptionWithDictionary:(NSDictionary *)dict standardEquipment:(NSArray *)extras optionalEquipment:(NSArray *)options
9688 NSMutableArray *mut_extras = [NSMutableArray arrayWithArray:extras];
9689 NSString *allOptions = [options componentsJoinedByString:@" "];
9691 NSMutableString *desc = [NSMutableString stringWithFormat:@"The %@.", [dict oo_stringForKey: KEY_NAME]];
9697 OOCargoQuantity extra_cargo = [dict oo_unsignedIntForKey:@"extra_cargo" defaultValue:15];
9698 [desc appendFormat:@" Cargo capacity %dt", max_cargo];
9699 BOOL canExpand = ([allOptions rangeOfString:@"EQ_CARGO_BAY"].location != NSNotFound);
9701 [desc appendFormat:@" (expandable to %dt at most starports)", max_cargo + extra_cargo];
9702 [desc appendString:@"."];
9706 float top_speed = [dict oo_intForKey:@"max_flight_speed"];
9707 [desc appendFormat:@" Top speed %.3fLS.", 0.001 * top_speed];
9710 if ([mut_extras
count])
9712 unsigned n_berths = 0;
9714 for (i = 0; i < [mut_extras count]; i++)
9716 NSString* item_key = [mut_extras oo_stringAtIndex:i];
9717 if ([item_key isEqual:
@"EQ_PASSENGER_BERTH"])
9720 [mut_extras removeObjectAtIndex:i--];
9726 [desc appendString:@" Includes luxury accomodation for a single passenger."];
9728 [desc appendFormat:@" Includes luxury accomodation for %d passengers.", n_berths];
9733 if ([mut_extras
count])
9735 [desc appendString:@"\nComes with"];
9737 for (i = 0; i < [mut_extras count]; i++)
9739 NSString* item_key = [mut_extras oo_stringAtIndex:i];
9740 NSString* item_desc =
nil;
9741 for (j = 0; ((j < [equipmentData count])&&(!item_desc)) ; j++)
9743 NSString *eq_type = [[equipmentData oo_arrayAtIndex:j] oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
9744 if ([eq_type isEqual:item_key])
9749 switch ([mut_extras
count] - i)
9752 [desc appendFormat:@" %@ fitted as standard.", item_desc];
9755 [desc appendFormat:@" %@ and", item_desc];
9758 [desc appendFormat:@" %@,", item_desc];
9766 if ([options
count])
9768 [desc appendString:@"\nCan additionally be outfitted with"];
9770 for (i = 0; i < [options count]; i++)
9772 NSString* item_key = [options oo_stringAtIndex:i];
9773 NSString* item_desc =
nil;
9774 for (j = 0; ((j < [equipmentData count])&&(!item_desc)) ; j++)
9776 NSString *eq_type = [[equipmentData oo_arrayAtIndex:j] oo_stringAtIndex:EQUIPMENT_KEY_INDEX];
9777 if ([eq_type isEqual:item_key])
9782 switch ([options
count] - i)
9785 [desc appendFormat:@" %@ at suitably equipped starports.", item_desc];
9788 [desc appendFormat:@" %@ and/or", item_desc];
9791 [desc appendFormat:@" %@,", item_desc];
9802- (HPVector) getWitchspaceExitPosition
9808- (Quaternion) getWitchspaceExitRotation
9811 Quaternion q_result;
9821 quaternion_normalize(&q_result);
9827- (HPVector) getSunSkimStartPositionForShip:(
ShipEntity*) ship
9843 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9844 if (v1.x||v1.y||v1.z)
9845 v1 = HPvector_normal(v1);
9849 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9850 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9856- (HPVector) getSunSkimEndPositionForShip:(
ShipEntity*) ship
9872 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9873 if (v1.x||v1.y||v1.z)
9874 v1 = HPvector_normal(v1);
9878 if (v2.x||v2.y||v2.z)
9879 v2 = HPvector_normal(v2);
9882 HPVector v3 = HPcross_product(v1, v2);
9883 if (v3.x||v3.y||v3.z)
9884 v3 = HPvector_normal(v3);
9888 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9889 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9890 v1.x += 15000 * v3.
x; v1.y += 15000 * v3.
y; v1.z += 15000 * v3.z;
9891 v1.x -= v0.
x; v1.y -= v0.
y; v1.z -= v0.z;
9892 if (v1.x||v1.y||v1.z)
9893 v1 = HPvector_normal(v1);
9896 v1.x *= radius; v1.y *= radius; v1.z *= radius;
9897 v1.x += v0.
x; v1.y += v0.
y; v1.z += v0.z;
9903- (NSArray *) listBeaconsWithCode:(NSString *)code
9905 NSMutableArray *result = [NSMutableArray array];
9906 Entity <OOBeaconEntity> *beacon = [
self firstBeacon];
9908 while (beacon !=
nil)
9910 NSString *beaconCode = [beacon beaconCode];
9911 if ([beaconCode rangeOfString:code options: NSCaseInsensitiveSearch].location != NSNotFound)
9913 [result addObject:beacon];
9915 beacon = [beacon nextBeacon];
9918 return [result sortedArrayUsingSelector:@selector(compareBeaconCodeWith:)];
9922- (void) allShipsDoScriptEvent:(jsid)event andReactToAIMessage:(NSString *)message
9925 int ent_count = n_entities;
9928 for (i = 0; i < ent_count; i++)
9930 if (sortedEntities[i]->isShip)
9936 for (i = 0; i < ship_count; i++)
9940 if (message !=
nil) [[se getAI] reactToMessage:message context:
@"global message"];
9955 return comm_log_gui;
9968 [message_gui clear];
9969 [comm_log_gui clear];
9970 [comm_log_gui printLongText:DESC(@"communications-log-string")
9971 align:GUI_ALIGN_CENTER color:[
OOColor yellowColor] fadeTime:0 key:nil addToArray:nil];
9975- (void) resetCommsLogColor
9981- (void) setDisplayText:(BOOL) value
9983 displayGUI = !!value;
9993- (void) setDisplayFPS:(BOOL) value
9995 displayFPS = !!value;
10005- (void) setAutoSave:(BOOL) value
10007 autoSave = !!value;
10008 [[NSUserDefaults standardUserDefaults] setBool:autoSave forKey:@"autosave"];
10018- (void) setAutoSaveNow:(BOOL) value
10020 autoSaveNow = !!value;
10024- (BOOL) autoSaveNow
10026 return autoSaveNow;
10030- (void) setWireframeGraphics:(BOOL) value
10032 wireframeGraphics = !!value;
10033 [[NSUserDefaults standardUserDefaults] setBool:wireframeGraphics forKey:@"wireframe-graphics"];
10037- (BOOL) wireframeGraphics
10039 return wireframeGraphics;
10043- (BOOL) reducedDetail
10064 detailLevel = value;
10071 [
self setDetailLevelDirectly:value];
10072 [[NSUserDefaults standardUserDefaults] setInteger:detailLevel forKey:@"detailLevel"];
10075 if (old != detailLevel)
10085 return detailLevel;
10095- (void) handleOoliteException:(NSException *)exception
10097 if (exception !=
nil)
10102 [player
setStatus:STATUS_HANDLING_ERROR];
10104 OOLog(
kOOLogException,
@"***** Handling Fatal : %@ : %@ *****",[exception name], [exception reason]);
10105 NSString* exception_msg = [NSString stringWithFormat:@"Exception : %@ : %@ Please take a screenshot and/or press esc or Q to quit.", [exception name], [exception reason]];
10106 [
self addMessage:exception_msg forCount:30.0];
10107 [[
self gameController] setGamePaused:YES];
10111 OOLog(
kOOLogException,
@"***** Handling Non-fatal : %@ : %@ *****",[exception name], [exception reason]);
10117- (GLfloat)airResistanceFactor
10119 return airResistanceFactor;
10123- (void) setAirResistanceFactor:(GLfloat)newFactor
10125 airResistanceFactor = OOClamp_0_1_f(newFactor);
10132- (void) startSpeakingString:(NSString *) text
10134 [speechSynthesizer startSpeakingString:[NSString stringWithFormat:@"[[volm %.3f]]%@", 0.3333333f * [
OOSound masterVolume], text]];
10138- (void) stopSpeaking
10140 if ([speechSynthesizer respondsToSelector:@selector(stopSpeakingAtBoundary:)])
10142 [speechSynthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary];
10146 [speechSynthesizer stopSpeaking];
10153 return [speechSynthesizer isSpeaking];
10158- (void) startSpeakingString:(NSString *) text
10160 NSData *utf8 = [text dataUsingEncoding:NSUTF8StringEncoding];
10164 const char *stringToSay = [text UTF8String];
10165 espeak_Synth(stringToSay, strlen(stringToSay) + 1 , 0, POS_CHARACTER, 0, espeakCHARS_UTF8 | espeakPHONEMES | espeakENDPAUSE, NULL, NULL);
10170- (void) stopSpeaking
10178 return espeak_IsPlaying();
10182- (NSString *) voiceName:(
unsigned int) index
10184 if (index >= espeak_voice_count)
10186 return [NSString stringWithCString: espeak_voices[index]->name];
10190- (
unsigned int) voiceNumber:(NSString *) name
10195 const char *
const label = [name UTF8String];
10199 unsigned int index = -1;
10200 while (espeak_voices[++index] && strcmp (espeak_voices[index]->name, label))
10202 return (index < espeak_voice_count) ? index : UINT_MAX;
10206- (
unsigned int) nextVoice:(
unsigned int) index
10208 if (++index >= espeak_voice_count)
10214- (
unsigned int) prevVoice:(
unsigned int) index
10216 if (--index >= espeak_voice_count)
10217 index = espeak_voice_count - 1;
10222- (
unsigned int) setVoice:(
unsigned int) index withGenderM:(BOOL) isMale
10224 if (index == UINT_MAX)
10225 index = [
self voiceNumber:DESC(@"espeak-default-voice")];
10227 if (index < espeak_voice_count)
10229 espeak_VOICE voice = { espeak_voices[index]->name, NULL, NULL, isMale ? 1 : 2 };
10230 espeak_SetVoiceByProperties (&voice);
10238- (void) startSpeakingString:(NSString *) text {}
10240- (void) stopSpeaking {}
10249- (BOOL) pauseMessageVisible
10251 return _pauseMessage;
10255- (void) setPauseMessageVisible:(BOOL)value
10257 _pauseMessage = value;
10261- (BOOL) permanentMessageLog
10263 return _permanentMessageLog;
10267- (void) setPermanentMessageLog:(BOOL)value
10269 _permanentMessageLog = value;
10273- (BOOL) autoMessageLogBg
10275 return _autoMessageLogBg;
10279- (void) setAutoMessageLogBg:(BOOL)value
10281 _autoMessageLogBg = !!value;
10285- (BOOL) permanentCommLog
10287 return _permanentCommLog;
10291- (void) setPermanentCommLog:(BOOL)value
10293 _permanentCommLog = value;
10297- (void) setAutoCommLog:(BOOL)value
10299 _autoCommLog = value;
10303- (BOOL) blockJSPlayerShipProps
10309- (void) setBlockJSPlayerShipProps:(BOOL)value
10322- (void) setUpSettings
10324 [
self resetBeacons];
10326 next_universal_id = 100;
10327 memset(entity_for_uid, 0,
sizeof entity_for_uid);
10329 [
self setMainLightPosition:kZeroVector];
10336 [message_gui autorelease];
10338 initWithPixelSize:NSMakeSize(480, 160)
10345 [comm_log_gui autorelease];
10347 initWithPixelSize:NSMakeSize(360, 120)
10358 [
self setTimeAccelerationFactor:TIME_ACCELERATION_FACTOR_DEFAULT];
10360 universal_time = 0.0;
10361 messageRepeatTime = 0.0;
10362 countdown_messageRepeatTime = 0.0;
10364#if OOLITE_SPEECH_SYNTH
10365 [speechArray autorelease];
10369 [commodities autorelease];
10373 [
self loadDescriptions];
10375 [characters autorelease];
10378 [customSounds autorelease];
10381 [globalSettings autorelease];
10385 [systemManager autorelease];
10388 [screenBackgrounds autorelease];
10392 [roleCategories autorelease];
10395 [autoAIMap autorelease];
10398 [equipmentData autorelease];
10399 [equipmentDataOutfitting autorelease];
10401 equipmentData = [[equipmentTemp sortedArrayUsingFunction:equipmentSort context:NULL] retain];
10402 equipmentDataOutfitting = [[equipmentTemp sortedArrayUsingFunction:equipmentSortOutfitting context:NULL] retain];
10406 [explosionSettings autorelease];
10414 NSMutableDictionary *tmp = [[NSMutableDictionary alloc] initWithCapacity:[commodities count]];
10416 foreach (type, [commodities goods])
10418 ShipEntity *container = [
self newShipWithRole:@"oolite-template-cargopod"];
10421 [tmp setObject:container forKey:type];
10422 [container release];
10424 [cargoPods release];
10425 cargoPods = [[NSDictionary alloc] initWithDictionary:tmp];
10432 NSMutableArray *badEntities =
nil;
10436 for (i = 0; i < n_entities; i++)
10438 entity = sortedEntities[i];
10439 if ([entity sessionID] != _sessionID)
10441 OOLogERR(
@"universe.sessionIDs.verify.failed",
@"Invalid entity %@ (came from session %llu, current session is %llu).", [entity shortDescription], [entity sessionID], _sessionID);
10442 if (badEntities ==
nil) badEntities = [NSMutableArray array];
10443 [badEntities addObject:entity];
10447 foreach (entity, badEntities)
10449 [
self removeEntity:entity];
10456- (BOOL) reinitAndShowDemo:(BOOL) showDemo
10460 assert(player !=
nil);
10471 [
self removeAllEntitiesExceptPlayer];
10484 [[
self gameController] setGamePaused:NO];
10485 [[
self gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
10486 [PLAYER setSpeed:0.0];
10488 [
self loadDescriptions];
10489 [
self loadScenarios];
10491 [missiontext autorelease];
10497 [demo_ships release];
10499 demo_ship_index = 0;
10500 demo_ship_subindex = 0;
10503 breakPatternCounter = 0;
10506 cachedPlanet =
nil;
10507 cachedStation =
nil;
10509 [
self setUpSettings];
10514 [
self setUpCargoPods];
10516 if (![player setUpAndConfirmOK:YES])
10525 [
self addEntity:player];
10527 [[
self gameController] setPlayerFileToLoad:nil];
10529 [
self setUpInitialUniverse];
10532 [[
self station] initialiseLocalMarket];
10555 [
self populateNormalSpace];
10566 [
self verifyEntitySessionIDs];
10578 if (activeWormholes) [activeWormholes autorelease];
10579 activeWormholes = [[NSMutableArray arrayWithCapacity:16] retain];
10580 if (characterPool) [characterPool autorelease];
10581 characterPool = [[NSMutableArray arrayWithCapacity:256] retain];
10585 [
self setGalaxyTo: [player
galaxyNumber] andReinit:YES];
10597 [
self setDockingClearanceProtocolActive:
10598 [[
self currentSystemData] oo_boolForKey:@"stations_require_docking_clearance" defaultValue:YES]];
10600 [
self enterGUIViewModeWithMouseInteraction:NO];
10612- (Vector) randomPlaceWithinScannerFrom:(Vector)pos alongRoute:(Vector)route withOffset:(
double)offset
10614 pos.x +=
offset * route.
x + [
self randomDistanceWithinScanner];
10615 pos.y +=
offset * route.
y + [
self randomDistanceWithinScanner];
10616 pos.z +=
offset * route.z + [
self randomDistanceWithinScanner];
10622- (HPVector) fractionalPositionFrom:(HPVector)point0 to:(HPVector)point1 withFraction:(
double)routeFraction
10624 if (routeFraction == NSNotFound) routeFraction =
randf();
10626 point1 = OOHPVectorInterpolate(point0, point1, routeFraction);
10636- (BOOL)doRemoveEntity:(
Entity *)entity
10639 if ([entity canCollide])
10641 doLinkedListMaintenanceThisUpdate = YES;
10649 entity_for_uid[old_id] =
nil;
10659 if (sortedEntities[index] != entity)
10661 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity:%@ ENTITY IS NOT IN THE RIGHT PLACE IN THE ZERO_DISTANCE SORTED LIST -- FIXING...", entity);
10664 for (i = 0; (i < n_entities)&&(index == -1); i++)
10665 if (sortedEntities[i] == entity)
10668 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity:%@ ENTITY IS NOT IN THE ZERO_DISTANCE SORTED LIST -- CONTINUING...", entity);
10672 while ((
unsigned)index < n_entities)
10674 while (((
unsigned)index + n < n_entities)&&(sortedEntities[index + n] == entity))
10693 sortedEntities[index] = sortedEntities[index + n];
10694 if (sortedEntities[index])
10696 sortedEntities[index]->zero_index = index;
10701 OOLog(
kOOLogInconsistentState,
@"DEBUG: Universe removeEntity: REMOVED %d EXTRA COPIES OF %@ FROM THE ZERO_DISTANCE SORTED LIST", n - 1, entity);
10705 sortedEntities[n_entities] =
nil;
10712 if ([entities containsObject:entity])
10715 if ([entity isBreakPattern] && ![entity isVisualEffect])
10717 breakPatternCounter--;
10720 if ([entity isShip])
10723 [
self clearBeacon:se];
10725 if ([entity isWaypoint])
10728 [
self clearBeacon:wp];
10730 if ([entity isVisualEffect])
10733 [
self clearBeacon:ve];
10736 if ([entity isWormhole])
10738 [activeWormholes removeObject:entity];
10740 else if ([entity isPlanet])
10742 [allPlanets removeObject:entity];
10745 [entities removeObject:entity];
10753static void PreloadOneSound(NSString *soundName)
10755 if (![soundName hasPrefix:
@"["] && ![soundName hasSuffix:@"]"])
10762- (void) preloadSounds
10765 NSString *key =
nil;
10768 id object = [customSounds objectForKey:key];
10769 if([
object isKindOfClass:[NSString class]])
10771 PreloadOneSound(
object);
10773 else if([
object isKindOfClass:[NSArray class]] && [object
count] > 0)
10775 NSString *soundName =
nil;
10776 foreach (soundName,
object)
10778 if ([soundName isKindOfClass:[NSString class]])
10780 PreloadOneSound(soundName);
10787 PreloadOneSound(
@"afterburner1.ogg");
10793 NSAutoreleasePool *pool =
nil;
10795 while ([activeWormholes
count])
10797 pool = [[NSAutoreleasePool alloc] init];
10803 if (![whole isScanned] &&
10804 NSEqualPoints([
PLAYER galaxy_coordinates], [whole destinationCoordinates]) )
10809 [activeWormholes removeObjectAtIndex:0];
10811 @catch (NSException *exception)
10813 OOLog(
kOOLogException,
@"Squashing exception during wormhole unpickling (%@: %@).", [exception name], [exception reason]);
10820- (NSString *)chooseStringForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary
10822 id object = [dictionary objectForKey:key];
10823 if ([
object isKindOfClass:[NSString class]]) return object;
10824 else if ([
object isKindOfClass:[NSArray class]] && [object
count] > 0) return [object oo_stringAtIndex:
Ranrot() % [object
count]];
10829#if OO_LOCALIZATION_TOOLS
10832- (void) dumpDebugGraphViz
10834 if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"universe-dump-debug-graphviz"])
10836 [
self dumpSystemDescriptionGraphViz];
10841- (void) dumpSystemDescriptionGraphViz
10843 NSMutableString *graphViz =
nil;
10844 NSArray *systemDescriptions =
nil;
10845 NSArray *thisDesc =
nil;
10846 NSUInteger i,
count, j, subCount;
10847 NSString *descLine =
nil;
10848 NSArray *curses =
nil;
10849 NSString *label =
nil;
10850 NSDictionary *keyMap =
nil;
10856 graphViz = [NSMutableString stringWithString:
10857 @"// System description grammar:\n\n"
10858 "digraph system_descriptions\n"
10860 "\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"
10861 "\tedge [arrowhead=dot]\n"
10862 "\tnode [shape=none height=0.2 width=3 fontname=Helvetica]\n\t\n"];
10864 systemDescriptions = [[
self descriptions] oo_arrayForKey:@"system_description"];
10865 count = [systemDescriptions count];
10868 descLine =
DESC(
@"system-description-string");
10870 [graphViz appendFormat:@"\tsystem_description_string [label=\"%@\" shape=ellipse]\n", EscapedGraphVizString(label)];
10871 [
self addNumericRefsInString:descLine
10872 toGraphViz:graphViz
10873 fromNode:@"system_description_string"
10875 [graphViz appendString:@"\t\n"];
10878 [graphViz appendString:
10879 @"\tpercent_I [label=\"%I\\nInhabitants\" shape=diamond]\n"
10880 "\tpercent_H [label=\"%H\\nSystem name\" shape=diamond]\n"
10881 "\tpercent_RN [label=\"%R/%N\\nRandom name\" shape=diamond]\n"
10882 "\tpercent_J [label=\"%J\\nNumbered system name\" shape=diamond]\n"
10883 "\tpercent_G [label=\"%G\\nNumbered system name in chart number\" shape=diamond]\n\t\n"];
10886 [graphViz appendString:@"\tsubgraph cluster_thargoid_curses\n\t{\n\t\tlabel = \"Thargoid curses\"\n"];
10887 curses = [[
self descriptions] oo_arrayForKey:@"thargoid_curses"];
10888 subCount = [curses count];
10889 for (j = 0; j < subCount; ++j)
10892 [graphViz appendFormat:@"\t\tthargoid_curse_%llu [label=\"%@\"]\n", j, EscapedGraphVizString(label)];
10894 [graphViz appendString:@"\t}\n"];
10895 for (j = 0; j < subCount; ++j)
10897 [
self addNumericRefsInString:[curses oo_stringAtIndex:j]
10898 toGraphViz:graphViz
10899 fromNode:[NSString stringWithFormat:@"thargoid_curse_%llu", j]
10902 [graphViz appendString:@"\t\n"];
10906 for (i = 0; i <
count; ++i)
10909 label = [keyMap objectForKey:[NSString stringWithFormat:@"%llu", i]];
10910 if (label ==
nil) label = [NSString stringWithFormat:
@"[%llu]", i];
10911 else label = [NSString stringWithFormat:@"[%llu] (%@)", i, label];
10913 [graphViz appendFormat:@"\tsubgraph cluster_%llu\n\t{\n\t\tlabel=\"%@\"\n", i, EscapedGraphVizString(label)];
10915 thisDesc = [systemDescriptions oo_arrayAtIndex:i];
10916 subCount = [thisDesc count];
10917 for (j = 0; j < subCount; ++j)
10920 [graphViz appendFormat:@"\t\tn%llu_%llu [label=\"\\\"%@\\\"\"]\n", i, j, EscapedGraphVizString(label)];
10923 [graphViz appendString:@"\t}\n"];
10925 [graphViz appendString:@"\t\n"];
10928 for (i = 0; i !=
count; ++i)
10930 thisDesc = [systemDescriptions oo_arrayAtIndex:i];
10931 subCount = [thisDesc count];
10932 for (j = 0; j != subCount; ++j)
10934 descLine = [thisDesc oo_stringAtIndex:j];
10935 [
self addNumericRefsInString:descLine
10936 toGraphViz:graphViz
10937 fromNode:[NSString stringWithFormat:@"n%llu_%llu", i, j]
10943 [graphViz appendString:@"\t}\n"];
10949- (void) addNumericRefsInString:(NSString *)string toGraphViz:(NSMutableString *)graphViz fromNode:(NSString *)fromNode nodeCount:(NSUInteger)nodeCount
10951 NSString *index =
nil;
10952 NSInteger start, end;
10953 NSRange remaining, subRange;
10956 remaining = NSMakeRange(0, [
string length]);
10960 subRange = [string rangeOfString:@"[" options:NSLiteralSearch range:remaining];
10961 if (subRange.location == NSNotFound)
break;
10962 start = subRange.location + subRange.length;
10963 remaining.length -= start - remaining.location;
10964 remaining.location = start;
10966 subRange = [string rangeOfString:@"]" options:NSLiteralSearch range:remaining];
10967 if (subRange.location == NSNotFound)
break;
10968 end = subRange.location;
10969 remaining.length -= end - remaining.location;
10970 remaining.location = end;
10972 index = [string substringWithRange:NSMakeRange(start, end - start)];
10973 i = [index intValue];
10976 [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];
10979 if ([
string rangeOfString:
@"%I"].location != NSNotFound)
10981 [graphViz appendFormat:@"\t%@ -> percent_I [color=\"0,0,0.25\"]\n", fromNode];
10983 if ([
string rangeOfString:
@"%H"].location != NSNotFound)
10985 [graphViz appendFormat:@"\t%@ -> percent_H [color=\"0,0,0.45\"]\n", fromNode];
10987 if ([
string rangeOfString:
@"%R"].location != NSNotFound || [string rangeOfString:
@"%N"].location != NSNotFound)
10989 [graphViz appendFormat:@"\t%@ -> percent_RN [color=\"0,0,0.65\"]\n", fromNode];
10993 if ([
string rangeOfString:
@"%J"].location != NSNotFound)
10995 [graphViz appendFormat:@"\t%@ -> percent_J [color=\"0,0,0.75\"]\n", fromNode];
10998 if ([
string rangeOfString:
@"%G"].location != NSNotFound)
11000 [graphViz appendFormat:@"\t%@ -> percent_G [color=\"0,0,0.85\"]\n", fromNode];
11008 NSArray *arguments =
nil;
11009 NSString *arg =
nil;
11010 BOOL compileSysDesc = NO, exportSysDesc = NO, xml = NO;
11012 arguments = [[NSProcessInfo processInfo] arguments];
11014 foreach (arg, arguments)
11016 if ([arg isEqual:
@"--compile-sysdesc"]) compileSysDesc = YES;
11017 else if ([arg isEqual:
@"--export-sysdesc"]) exportSysDesc = YES;
11018 else if ([arg isEqual:
@"--xml"]) xml = YES;
11019 else if ([arg isEqual:
@"--openstep"]) xml = NO;
11030- (void) prunePreloadingPlanetMaterials
11034 NSUInteger i = [_preloadingPlanetMaterials count];
11037 if ([[_preloadingPlanetMaterials objectAtIndex:i] isFinishedLoading])
11039 [_preloadingPlanetMaterials removeObjectAtIndex:i];
11047- (void) loadConditionScripts
11049 [conditionScripts autorelease];
11050 conditionScripts = [[NSMutableDictionary alloc] init];
11060- (void) addConditionScripts:(NSEnumerator *)scripts
11062 NSString *scriptname =
nil;
11063 while ((scriptname = [scripts nextObject]))
11065 if ([conditionScripts objectForKey:scriptname] ==
nil)
11070 [conditionScripts setObject:script forKey:scriptname];
11077- (
OOJSScript*) getConditionScript:(NSString *)scriptname
11079 return [conditionScripts objectForKey:scriptname];
11085@implementation OOSound (OOCustomSounds)
11087+ (id) soundWithCustomSoundKey:(NSString *)key
11089 NSString *fileName = [UNIVERSE soundNameForCustomSoundKey:key];
11090 if (fileName ==
nil)
return nil;
11095- (id) initWithCustomSoundKey:(NSString *)key
11104@implementation OOSoundSource (OOCustomSounds)
11106+ (id) sourceWithCustomSoundKey:(NSString *)key
11108 return [[[
self alloc] initWithCustomSoundKey:key] autorelease];
11112- (id) initWithCustomSoundKey:(NSString *)key
11115 if (theSound !=
nil)
11117 self = [
self initWithSound:theSound];
11128- (void) playCustomSoundWithKey:(NSString *)key
11131 if (theSound !=
nil) [
self playSound:theSound];
11138 NSDictionary *one = (NSDictionary *)a;
11139 NSDictionary *two = (NSDictionary *)b;
11140 int pri_one = [one oo_intForKey:@"priority" defaultValue:100];
11141 int pri_two = [two oo_intForKey:@"priority" defaultValue:100];
11142 if (pri_one < pri_two)
return NSOrderedAscending;
11143 if (pri_one > pri_two)
return NSOrderedDescending;
11144 return NSOrderedSame;
11150 NSArray *one = (NSArray *)a;
11151 NSArray *two = (NSArray *)b;
11155 OOCreditsQuantity comp1 = [[one oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000];
11156 OOCreditsQuantity comp2 = [[two oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] oo_unsignedLongLongForKey:@"sort_order" defaultValue:1000];
11157 if (comp1 < comp2)
return NSOrderedAscending;
11158 if (comp1 > comp2)
return NSOrderedDescending;
11160 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11161 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11162 if (comp1 < comp2)
return NSOrderedAscending;
11163 if (comp1 > comp2)
return NSOrderedDescending;
11165 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11166 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11167 if (comp1 < comp2)
return NSOrderedAscending;
11168 if (comp1 > comp2)
return NSOrderedDescending;
11170 return NSOrderedSame;
11176 NSArray *one = (NSArray *)a;
11177 NSArray *two = (NSArray *)b;
11181 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]];
11182 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]];
11183 if (comp1 < comp2)
return NSOrderedAscending;
11184 if (comp1 > comp2)
return NSOrderedDescending;
11186 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11187 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_TECH_LEVEL_INDEX];
11188 if (comp1 < comp2)
return NSOrderedAscending;
11189 if (comp1 > comp2)
return NSOrderedDescending;
11191 comp1 = [one oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11192 comp2 = [two oo_unsignedLongLongAtIndex:EQUIPMENT_PRICE_INDEX];
11193 if (comp1 < comp2)
return NSOrderedAscending;
11194 if (comp1 > comp2)
return NSOrderedDescending;
11196 return NSOrderedSame;
11202 NSString *result = [UNIVERSE descriptionForKey:key];
11203 if (result ==
nil) result = key;
11211 NSArray *conditions = [[UNIVERSE descriptions] oo_arrayForKey:@"plural-rules"];
11214 NSString *tmp = [UNIVERSE descriptionForKey:key];
11217 static NSMutableSet *warned =
nil;
11219 if (![warned containsObject:tmp])
11221 OOLogWARN(
@"localization.plurals",
@"'%@' found in descriptions.plist, should be '%@%%0'. Localization data needs updating.",key,key);
11222 if (warned ==
nil) warned = [[NSMutableSet alloc] init];
11223 [warned addObject:tmp];
11227 if (conditions ==
nil)
11237 for (index = i = 0; i < [conditions count]; ++index, ++i)
11239 const char *cond = [[conditions oo_stringAtIndex:i] UTF8String];
11243 long int input =
count;
11246 while (isspace (*cond))
11251 while (isspace (*cond))
11254 char command = *cond++;
11266 long int param = strtol(cond, (
char **)&cond, 10);
11281 if (flag ^ (input == param))
11285 if (flag ^ (input != param))
11290 if (flag ^ (input < param))
11294 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)
OOINLINE jsval OOJSValueFromViewID(JSContext *context, OOViewID value)
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 setLastDrawCounter:(NSUInteger drawCounter)
void setScanClass:(OOScanClass sClass)
void setPositionX:y:z:(OOHPScalar x,[y] OOHPScalar y,[z] OOHPScalar z)
HPVector absolutePositionForSubentityOffset:(HPVector offset)
GLfloat cameraRangeBack()
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 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()
OOMaterial * atmosphereMaterial()
void setOrientation:(Quaternion quat)
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