Got Instruments working and fixed several small leaks. Currently mostly seeing occasional leaks of OOWeakReferences to ships (but the ships themselves aren't leaked and OOWeakReferences are only 8 bytes.) Cobbled together a class for handling groups of sources for related sounds, so that e.g. the number of simultanous scrape sounds is limited. Moved bits of player launching logic from pollDockedControls: to leaveDock: (which is also called from other places).

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1465 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2008-03-08 17:16:10 +00:00
parent fe418babea
commit 3f74d1b923
26 changed files with 732 additions and 347 deletions

View File

@ -26,7 +26,7 @@ endif
OBJC_PROGRAM_NAME = oolite OBJC_PROGRAM_NAME = oolite
oolite_C_FILES = legacy_random.c strlcpy.c OOTCPStreamDecoder.c oolite_C_FILES = legacy_random.c strlcpy.c OOTCPStreamDecoder.c
oolite_OBJC_FILES = OOCocoa.m Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m Universe.m OOSound.m SDLMusic.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m OOTexture.m OOTextureLoader.m OOPNGTextureLoader.m OOOpenGLExtensionManager.m OOBasicMaterial.m OOSingleTextureMaterial.m OOCPUInfo.m OOSelfDrawingEntity.m OOEntityWithDrawable.m OODrawable.m OOJSVector.m OOMesh.m OOOpenGL.m OOGraphicsResetManager.m OOProbabilisticTextureManager.m OODebugGLDrawing.m OOShaderUniformMethodType.m OOAsyncQueue.m TextureStore.m OOOXPVerifier.m OOOXPVerifierStage.m OOFileScannerVerifierStage.m OOCheckRequiresPListVerifierStage.m OOCheckDemoShipsPListVerifierStage.m OOCheckEquipmentPListVerifierStage.m OOTextureVerifierStage.m OOModelVerifierStage.m OOCheckShipDataPListVerifierStage.m OOPListSchemaVerifier.m OOJSShip.m OOJSPlayer.m OOJSCall.m OOJSStation.m OOJSSystem.m OOLegacyEventHandlerScript.m OOJSOolite.m OORoleSet.m OOJSGlobal.m OOJSMissionVariables.m OOJSMission.m OOPriorityQueue.m OOScriptTimer.m OOJSTimer.m OOJSClock.m OODebugSupport.m OODebugMonitor.m OOJSConsole.m OODebugTCPConsoleClient.m OOTCPStreamDecoderAbstractionLayer.m OOEntityFilterPredicate.m OOJSPlanet.m OOJSWorldScripts.m OOJSSun.m NSThreadOOExtensions.m OOEncodingConverter.m OOJSSound.m OOJSSoundSource.m OOMusicController.m OOLogHeader.m OOJSSpecialFunctions.m OOSpatialReference.m OOSkyDrawable.m OOFilteringEnumerator.m oolite_OBJC_FILES = OOCocoa.m Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m Universe.m OOSound.m SDLMusic.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m OOTexture.m OOTextureLoader.m OOPNGTextureLoader.m OOOpenGLExtensionManager.m OOBasicMaterial.m OOSingleTextureMaterial.m OOCPUInfo.m OOSelfDrawingEntity.m OOEntityWithDrawable.m OODrawable.m OOJSVector.m OOMesh.m OOOpenGL.m OOGraphicsResetManager.m OOProbabilisticTextureManager.m OODebugGLDrawing.m OOShaderUniformMethodType.m OOAsyncQueue.m TextureStore.m OOOXPVerifier.m OOOXPVerifierStage.m OOFileScannerVerifierStage.m OOCheckRequiresPListVerifierStage.m OOCheckDemoShipsPListVerifierStage.m OOCheckEquipmentPListVerifierStage.m OOTextureVerifierStage.m OOModelVerifierStage.m OOCheckShipDataPListVerifierStage.m OOPListSchemaVerifier.m OOJSShip.m OOJSPlayer.m OOJSCall.m OOJSStation.m OOJSSystem.m OOLegacyEventHandlerScript.m OOJSOolite.m OORoleSet.m OOJSGlobal.m OOJSMissionVariables.m OOJSMission.m OOPriorityQueue.m OOScriptTimer.m OOJSTimer.m OOJSClock.m OODebugSupport.m OODebugMonitor.m OOJSConsole.m OODebugTCPConsoleClient.m OOTCPStreamDecoderAbstractionLayer.m OOEntityFilterPredicate.m OOJSPlanet.m OOJSWorldScripts.m OOJSSun.m NSThreadOOExtensions.m OOEncodingConverter.m OOJSSound.m OOJSSoundSource.m OOMusicController.m OOLogHeader.m OOJSSpecialFunctions.m OOSpatialReference.m OOSkyDrawable.m OOFilteringEnumerator.m OOSoundSourcePool.m
include $(GNUSTEP_MAKEFILES)/objc.make include $(GNUSTEP_MAKEFILES)/objc.make
include GNUmakefile.postamble include GNUmakefile.postamble

View File

@ -514,6 +514,8 @@
1AC775E20C2DD4E900ECFF3B /* OODebugGLDrawing.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AC775E00C2DD4E900ECFF3B /* OODebugGLDrawing.h */; }; 1AC775E20C2DD4E900ECFF3B /* OODebugGLDrawing.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AC775E00C2DD4E900ECFF3B /* OODebugGLDrawing.h */; };
1AC775E30C2DD4E900ECFF3B /* OODebugGLDrawing.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AC775E10C2DD4E900ECFF3B /* OODebugGLDrawing.m */; }; 1AC775E30C2DD4E900ECFF3B /* OODebugGLDrawing.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AC775E10C2DD4E900ECFF3B /* OODebugGLDrawing.m */; };
1AC973FA0C9847850010C42B /* pirate-victim-roles.plist in Copy Config */ = {isa = PBXBuildFile; fileRef = 1AC973F90C9847850010C42B /* pirate-victim-roles.plist */; }; 1AC973FA0C9847850010C42B /* pirate-victim-roles.plist in Copy Config */ = {isa = PBXBuildFile; fileRef = 1AC973F90C9847850010C42B /* pirate-victim-roles.plist */; };
1ACBF0AD0D82F79600CC005F /* OOSoundSourcePool.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACBF06F0D82DF9B00CC005F /* OOSoundSourcePool.h */; };
1ACBF0AE0D82F79800CC005F /* OOSoundSourcePool.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ACBF0700D82DF9B00CC005F /* OOSoundSourcePool.m */; };
1ACE208F0D805F78009F6957 /* oolite-scarred-metal-specular.png in Resources */ = {isa = PBXBuildFile; fileRef = 1ACE208E0D805F78009F6957 /* oolite-scarred-metal-specular.png */; }; 1ACE208F0D805F78009F6957 /* oolite-scarred-metal-specular.png in Resources */ = {isa = PBXBuildFile; fileRef = 1ACE208E0D805F78009F6957 /* oolite-scarred-metal-specular.png */; };
1ACEA3490C91507000C7CE97 /* OORoleSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACEA3470C91507000C7CE97 /* OORoleSet.h */; }; 1ACEA3490C91507000C7CE97 /* OORoleSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACEA3470C91507000C7CE97 /* OORoleSet.h */; };
1ACEA34A0C91507000C7CE97 /* OORoleSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ACEA3480C91507000C7CE97 /* OORoleSet.m */; }; 1ACEA34A0C91507000C7CE97 /* OORoleSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ACEA3480C91507000C7CE97 /* OORoleSet.m */; };
@ -1026,7 +1028,7 @@
1A2315510B9C778400EF0852 /* trumblebox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = trumblebox.png; sourceTree = "<group>"; }; 1A2315510B9C778400EF0852 /* trumblebox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = trumblebox.png; sourceTree = "<group>"; };
1A2316DE0B9CFAD700EF0852 /* characters.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = characters.plist; sourceTree = "<group>"; }; 1A2316DE0B9CFAD700EF0852 /* characters.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = characters.plist; sourceTree = "<group>"; };
1A2316DF0B9CFAD700EF0852 /* commodities.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = commodities.plist; sourceTree = "<group>"; }; 1A2316DF0B9CFAD700EF0852 /* commodities.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = commodities.plist; sourceTree = "<group>"; };
1A2316E00B9CFAD700EF0852 /* customsounds.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = customsounds.plist; sourceTree = "<group>"; }; 1A2316E00B9CFAD700EF0852 /* customsounds.plist */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = customsounds.plist; sourceTree = "<group>"; };
1A2316E10B9CFAD700EF0852 /* demoships.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = demoships.plist; sourceTree = "<group>"; }; 1A2316E10B9CFAD700EF0852 /* demoships.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = demoships.plist; sourceTree = "<group>"; };
1A2316E20B9CFAD700EF0852 /* descriptions.plist */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = descriptions.plist; sourceTree = "<group>"; }; 1A2316E20B9CFAD700EF0852 /* descriptions.plist */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = descriptions.plist; sourceTree = "<group>"; };
1A2316E30B9CFAD700EF0852 /* equipment.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = equipment.plist; sourceTree = "<group>"; }; 1A2316E30B9CFAD700EF0852 /* equipment.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = equipment.plist; sourceTree = "<group>"; };
@ -1504,6 +1506,8 @@
1AC775E00C2DD4E900ECFF3B /* OODebugGLDrawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OODebugGLDrawing.h; sourceTree = "<group>"; }; 1AC775E00C2DD4E900ECFF3B /* OODebugGLDrawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OODebugGLDrawing.h; sourceTree = "<group>"; };
1AC775E10C2DD4E900ECFF3B /* OODebugGLDrawing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OODebugGLDrawing.m; sourceTree = "<group>"; }; 1AC775E10C2DD4E900ECFF3B /* OODebugGLDrawing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OODebugGLDrawing.m; sourceTree = "<group>"; };
1AC973F90C9847850010C42B /* pirate-victim-roles.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = "pirate-victim-roles.plist"; sourceTree = "<group>"; }; 1AC973F90C9847850010C42B /* pirate-victim-roles.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = "pirate-victim-roles.plist"; sourceTree = "<group>"; };
1ACBF06F0D82DF9B00CC005F /* OOSoundSourcePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOSoundSourcePool.h; sourceTree = "<group>"; };
1ACBF0700D82DF9B00CC005F /* OOSoundSourcePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOSoundSourcePool.m; sourceTree = "<group>"; };
1ACE208E0D805F78009F6957 /* oolite-scarred-metal-specular.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "oolite-scarred-metal-specular.png"; sourceTree = "<group>"; }; 1ACE208E0D805F78009F6957 /* oolite-scarred-metal-specular.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "oolite-scarred-metal-specular.png"; sourceTree = "<group>"; };
1ACEA3470C91507000C7CE97 /* OORoleSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OORoleSet.h; sourceTree = "<group>"; }; 1ACEA3470C91507000C7CE97 /* OORoleSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OORoleSet.h; sourceTree = "<group>"; };
1ACEA3480C91507000C7CE97 /* OORoleSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OORoleSet.m; sourceTree = "<group>"; }; 1ACEA3480C91507000C7CE97 /* OORoleSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OORoleSet.m; sourceTree = "<group>"; };
@ -2359,6 +2363,8 @@
1AAB9A960D779F3C00A9F424 /* OOCocoa.m */, 1AAB9A960D779F3C00A9F424 /* OOCocoa.m */,
1A1616600D7DCFDC0094AE5B /* OOFilteringEnumerator.h */, 1A1616600D7DCFDC0094AE5B /* OOFilteringEnumerator.h */,
1A1616610D7DCFDC0094AE5B /* OOFilteringEnumerator.m */, 1A1616610D7DCFDC0094AE5B /* OOFilteringEnumerator.m */,
1ACBF06F0D82DF9B00CC005F /* OOSoundSourcePool.h */,
1ACBF0700D82DF9B00CC005F /* OOSoundSourcePool.m */,
); );
name = Utilities; name = Utilities;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2810,6 +2816,7 @@
1A5218DA0D72EC21000865E9 /* OOSpatialReference.h in Headers */, 1A5218DA0D72EC21000865E9 /* OOSpatialReference.h in Headers */,
1A03658A0D7CA05000B5F46F /* OOSkyDrawable.h in Headers */, 1A03658A0D7CA05000B5F46F /* OOSkyDrawable.h in Headers */,
1A1616620D7DCFDC0094AE5B /* OOFilteringEnumerator.h in Headers */, 1A1616620D7DCFDC0094AE5B /* OOFilteringEnumerator.h in Headers */,
1ACBF0AD0D82F79600CC005F /* OOSoundSourcePool.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -3161,6 +3168,7 @@
1AAB9A980D779F4500A9F424 /* OOCocoa.m in Sources */, 1AAB9A980D779F4500A9F424 /* OOCocoa.m in Sources */,
1A0365890D7CA05000B5F46F /* OOSkyDrawable.m in Sources */, 1A0365890D7CA05000B5F46F /* OOSkyDrawable.m in Sources */,
1A1616630D7DCFDC0094AE5B /* OOFilteringEnumerator.m in Sources */, 1A1616630D7DCFDC0094AE5B /* OOFilteringEnumerator.m in Sources */,
1ACBF0AE0D82F79800CC005F /* OOSoundSourcePool.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -1,84 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?> {
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> // Damage
<plist version="1.0"> "[player-hit-by-weapon]" = "hit.ogg"; // Hit by weapon
<dict> "[player-direct-hit]" = "hullbang.ogg"; // Hit by weapon while shield down ([player-hit-by-weapon] and [player-direct-hit] play at once)
<!-- list all possible custom sounds here --> "[player-scrape-damage]" = "hullbang.ogg"; // Touched another ship (or docking bay)
<!-- implemented: just the test sound -->
<key>[test]</key> // Outgoing weapons fire
<string>buy.ogg</string> "[player-laser-hit]" = "laserhits.ogg";
<!-- unimplmented: "[player-laser-miss]" = "laser.ogg";
<key>[witch-blocked-by-@]</key> "[energy-bomb-fired]" = "bigbang.ogg";
<string>buy.ogg</string>
<key>[witch-no-fuel]</key> // Warnings
<string>buy.ogg</string> "[hostile-warning]" = "warning.ogg";
<key>[witch-no-target]</key> "[alert-condition-red]" = "warning.ogg";
<string>buy.ogg</string> "[incoming-missile]" = "warning.ogg"; // Help, help, they're shooting at us
<key>[incoming-missile]</key> // "[energy-low]" = ""; // Energy below 25% - may occur repeatedly
<string>buy.ogg</string> "[autopilot-denied]" = "warning.ogg"; // Station refuses docking clearance
<key>[energy-low]</key> "[witchdrive-malfunction]" = "ecm.ogg"; // Misjump (3/4 witchjump malfunctions)
<string>buy.ogg</string> "[witchdrive-failure]" = "warning.ogg"; // Jump failed, internal damage (1/8 witchjump malfunctions; other 1/8 is fuel leak, see [fuel-leak])
<key>[autopilot-on]</key> "[fuel-leak]" = "warning.ogg";
<string>buy.ogg</string>
<key>[autopilot-off]</key> // Tunnel effects
<string>buy.ogg</string> "[player-launch-from-station]" = "breakpattern.ogg";
<key>[autopilot-cannot-dock-with-target]</key> "[player-dock-with-station]" = "breakpattern.ogg";
<string>buy.ogg</string> "[player-exit-witchspace]" = "breakpattern.ogg";
<key>[autopilot-denied]</key>
<string>buy.ogg</string> // ECM
<key>[autopilot-out-of-range]</key> "[player-fired-ecm]" = "ecm.ogg";
<string>buy.ogg</string> "[player-hit-by-ecm]" = "ecm.ogg";
<key>[aegis-planet]</key>
<string>buy.ogg</string> "[game-over]" = "bigbang.ogg";
<key>[aegis-station]</key>
<string>buy.ogg</string> /* The following can also be overriden:
<key>[mine-armed]</key> "[aegis-planet]" = "";
<string>buy.ogg</string> "[aegis-station]" = "";
<key>[mine-launched]</key> "[autopilot-cannot-dock-with-target]" = "";
<string>buy.ogg</string> "[autopilot-off]" = "";
<key>[missile-armed]</key> "[autopilot-on]" = "";
<string>buy.ogg</string> "[autopilot-out-of-range]" = "";
<key>[missile-locked-on]</key> "[cargo-jettisoned]" = "";
<string>buy.ogg</string> "[cloaking-device-off]" = "";
<key>[missile-launched]</key> "[cloaking-device-on]" = "";
<string>buy.ogg</string> "[escape-pod-scooped]" = "";
<key>[missile-safe]</key> "[galactic-hyperspace-countdown-begun]" = "";
<string>buy.ogg</string> "[game-over]" = "";
<key>[weapon-overheat]</key> "[hold-full]" = "";
<string>buy.ogg</string> "[hyperspace-countdown-aborted]" = "";
<key>[game-over]</key> "[hyperspace-countdown-begun]" = "";
<string>buy.ogg</string> "[ident-locked-on]" = "";
<key>[witchdrive-malfunction]</key> "[ident-off]" = "";
<string>buy.ogg</string> "[ident-on]" = "";
<key>[ident-on]</key> "[incoming-missile]" = "";
<string>buy.ogg</string> "[jump-mass-locked]" = "";
<key>[ident-off]</key> "[mine-armed]" = "";
<string>buy.ogg</string> "[mine-launched]" = "";
<key>[ident-locked-on]</key> "[missile-armed]" = "";
<string>buy.ogg</string> "[missile-launched]" = "";
<key>[no-target-in-memory]</key> "[missile-locked-on]" = "";
<string>buy.ogg</string> "[missile-safe]" = "";
<key>[target-lost]</key> "[no-target-in-memory]" = "";
<string>buy.ogg</string> "[target-lost]" = "";
<key>[hold-full]</key> "[weapon-overheat]" = "";
<string>buy.ogg</string> "[witch-blocked-by-@]" = "";
<key>[cargo-jettisoned]</key> "[witch-no-fuel]" = "";
<string>buy.ogg</string> "[witch-no-target]" = "";
<key>[hyperspace-countdown-begun]</key> "[wormhole-created]" = "";
<string>buy.ogg</string> */
<key>[galactic-hyperspace-countdown-begun]</key> }
<string>buy.ogg</string>
<key>[hyperspace-countdown-aborted]</key>
<string>buy.ogg</string>
<key>[cloaking-device-on]</key>
<string>buy.ogg</string>
<key>[cloaking-device-off]</key>
<string>buy.ogg</string>
<key>[jump-mass-locked]</key>
<string>buy.ogg</string>
<key>[wormhole-created]</key>
<string>buy.ogg</string>
<key>[escape-pod-scooped]</key>
<string>buy.ogg</string>
-->
</dict>
</plist>

View File

@ -69,7 +69,6 @@ SOFTWARE.
+ (id)sourceWithSound:(OOSound *)inSound; + (id)sourceWithSound:(OOSound *)inSound;
- (id)initWithSound:(OOSound *)inSound; - (id)initWithSound:(OOSound *)inSound;
- (id)init;
// These options should be set before playing. Effect of setting them while playing is undefined. // These options should be set before playing. Effect of setting them while playing is undefined.
- (OOSound *)sound; - (OOSound *)sound;

View File

@ -52,12 +52,6 @@ SOFTWARE.
#pragma mark NSObject #pragma mark NSObject
- (id)init
{
return [super init];
}
- (void)dealloc - (void)dealloc
{ {
[self stop]; [self stop];

View File

@ -168,7 +168,7 @@ static AI *sCurrentlyRunningAI = nil;
if ([aiStack count] > 32) if ([aiStack count] > 32)
{ {
OOLog(@"ai.pushStateMachine.overflow", @"***** ERROR: AI stack overflow for %@ stack:\n%@", _owner, aiStack); OOLog(@"ai.pushStateMachine.overflow", @"***** ERROR: AI stack overflow for %@ stack:\n%@", [_owner shortDescription], aiStack);
[NSException raise:@"OoliteException" [NSException raise:@"OoliteException"
format:@"AI stack overflow for %@", _owner]; format:@"AI stack overflow for %@", _owner];
} }

View File

@ -280,17 +280,9 @@ typedef enum
OOSound *beepSound; OOSound *beepSound;
OOSound *boopSound; OOSound *boopSound;
OOSound *weaponSound;
OOSound *weaponHitSound;
OOSound *missileSound; OOSound *missileSound;
OOSound *damageSound;
OOSound *scrapeDamageSound;
OOSound *destructionSound;
OOSound *breakPatternSound;
OOSound *ecmSound;
OOSound *buySound; OOSound *buySound;
OOSound *sellSound; OOSound *sellSound;
OOSound *warningSound;
OOSound *afterburner1Sound; OOSound *afterburner1Sound;
OOSound *afterburner2Sound; OOSound *afterburner2Sound;
OOSound *witchAbortSound; OOSound *witchAbortSound;

View File

@ -1773,7 +1773,6 @@ double scoopSoundPlayTime = 0.0;
else else
{ {
ecm_in_operation = NO; ecm_in_operation = NO;
[self stopECMSound];
[UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[ecm-out-of-juice]") forCount:3.0]; [UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[ecm-out-of-juice]") forCount:3.0];
} }
if ([UNIVERSE getTime] > ecm_start_time + ECM_DURATION) if ([UNIVERSE getTime] > ecm_start_time + ECM_DURATION)
@ -2620,21 +2619,20 @@ double scoopSoundPlayTime = 0.0;
if ([ms isEqual:@"INCOMING_MISSILE"]) if ([ms isEqual:@"INCOMING_MISSILE"])
{ {
if (![UNIVERSE playCustomSound:@"[incoming-missile]"]) [warningSound play]; [self playIncomingMissile];
[UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[incoming-missile]") forCount:4.5]; [UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[incoming-missile]") forCount:4.5];
} }
if ([ms isEqual:@"ENERGY_LOW"]) if ([ms isEqual:@"ENERGY_LOW"])
{ {
[UNIVERSE playCustomSound:@"[energy-low]"];
[UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[energy-low]") forCount:6.0]; [UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[energy-low]") forCount:6.0];
} }
if ([ms isEqual:@"ECM"]) [self playECMSound]; if ([ms isEqual:@"ECM"]) [self playHitByECMSound];
if ([ms isEqual:@"DOCKING_REFUSED"]&&(status == STATUS_AUTOPILOT_ENGAGED)) if ([ms isEqual:@"DOCKING_REFUSED"]&&(status == STATUS_AUTOPILOT_ENGAGED))
{ {
if (![UNIVERSE playCustomSound:@"[autopilot-denied]"]) [warningSound play]; [self playDockingDenied];
[UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[autopilot-denied]") forCount:4.5]; [UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[autopilot-denied]") forCount:4.5];
autopilot_engaged = NO; autopilot_engaged = NO;
primaryTarget = NO_TARGET; primaryTarget = NO_TARGET;
@ -2819,7 +2817,7 @@ double scoopSoundPlayTime = 0.0;
} }
} }
[UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[energy-bomb-activated]") forCount:4.5]; [UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[energy-bomb-activated]") forCount:4.5];
[destructionSound play]; [UNIVERSE playCustomSound:@"[energy-bomb-fired]"];
return YES; return YES;
} }
@ -2971,14 +2969,7 @@ double scoopSoundPlayTime = 0.0;
d_forward = dot_product(rel_pos, v_forward); d_forward = dot_product(rel_pos, v_forward);
if (damageSound) [self playShieldHit];
{
#if 0
// FIXME: should use an OOSoundSource.
if ([damageSound isPlaying]) [damageSound stop];
[damageSound play];
#endif
}
// firing on an innocent ship is an offence // firing on an innocent ship is an offence
if ((other)&&(other->isShip)) if ((other)&&(other->isShip))
@ -3017,14 +3008,7 @@ double scoopSoundPlayTime = 0.0;
{ {
internal_damage = ((ranrot_rand() & PLAYER_INTERNAL_DAMAGE_FACTOR) < amount); // base chance of damage to systems internal_damage = ((ranrot_rand() & PLAYER_INTERNAL_DAMAGE_FACTOR) < amount); // base chance of damage to systems
energy -= amount; energy -= amount;
if (scrapeDamageSound) [self playDirectHit];
{
#if 0
// FIXME: should use an OOSoundSource.
if ([scrapeDamageSound isPlaying]) [scrapeDamageSound stop];
#endif
[scrapeDamageSound play];
}
ship_temperature += amount; ship_temperature += amount;
} }
@ -3057,15 +3041,8 @@ double scoopSoundPlayTime = 0.0;
rel_pos = ent ? [ent position] : kZeroVector; rel_pos = ent ? [ent position] : kZeroVector;
rel_pos = vector_subtract(rel_pos, position); rel_pos = vector_subtract(rel_pos, position);
d_forward = dot_product(rel_pos, v_forward); d_forward = dot_product(rel_pos, v_forward);
if (scrapeDamageSound) [self playScrapeDamage];
{
#if 0
// FIXME: should use an OOSoundSource.
if ([scrapeDamageSound isPlaying]) [scrapeDamageSound stop];
#endif
[scrapeDamageSound play];
}
if (d_forward >= 0) if (d_forward >= 0)
{ {
forward_shield -= amount; forward_shield -= amount;
@ -3464,7 +3441,6 @@ double scoopSoundPlayTime = 0.0;
[self moveForward:100.0]; [self moveForward:100.0];
[UNIVERSE playCustomSound:@"[game-over]"]; [UNIVERSE playCustomSound:@"[game-over]"];
[destructionSound play];
flightSpeed = 160.0; flightSpeed = 160.0;
status = STATUS_DEAD; status = STATUS_DEAD;
@ -3533,7 +3509,7 @@ double scoopSoundPlayTime = 0.0;
[self setOrientation: kIdentityQuaternion]; // reset orientation to dock [self setOrientation: kIdentityQuaternion]; // reset orientation to dock
[UNIVERSE set_up_break_pattern:position quaternion:orientation]; [UNIVERSE set_up_break_pattern:position quaternion:orientation];
[self playBreakPattern]; [self playDockWithStation];
[station noteDockedShip:self]; [station noteDockedShip:self];
dockedStation = station; dockedStation = station;
@ -3621,10 +3597,17 @@ double scoopSoundPlayTime = 0.0;
- (void) leaveDock:(StationEntity *)station - (void) leaveDock:(StationEntity *)station
{ {
if (station == nil) return; if (station == nil) return;
// ensure we've not left keyboard entry on
[[UNIVERSE gameView] allowStringInput: NO];
if (gui_screen == GUI_SCREEN_MISSION) [self doScriptEvent:@"missionScreenEnded"];
if (station == [UNIVERSE station]) if (station == [UNIVERSE station])
{
legalStatus |= [UNIVERSE legal_status_of_manifest:shipCommodityData]; // 'leaving with those guns were you sir?' legalStatus |= [UNIVERSE legal_status_of_manifest:shipCommodityData]; // 'leaving with those guns were you sir?'
}
[self loadCargoPods]; [self loadCargoPods];
// clear the way // clear the way
@ -3653,6 +3636,27 @@ double scoopSoundPlayTime = 0.0;
ship_clock_adjust = 600.0; // 10 minutes to leave dock ship_clock_adjust = 600.0; // 10 minutes to leave dock
dockedStation = nil; dockedStation = nil;
suppressAegisMessages = YES;
#if 0
// "Fix" for "simple" issue where space compass shows station with planet icon on launch.
// Has the slight unwanted side-effect of effectively giving the player an advanced compass.
if ([self checkForAegis] != AEGIS_NONE)
{
[self setCompassMode:COMPASS_MODE_STATION];
}
else
{
[self setCompassMode:COMPASS_MODE_PLANET];
}
#else
[self checkForAegis];
#endif
suppressAegisMessages = NO;
ident_engaged = NO;
[self playLaunchFromStation];
} }
@ -3850,10 +3854,12 @@ double scoopSoundPlayTime = 0.0;
if (malfunc) if (malfunc)
{ {
if (randf() > 0.5) if (randf() > 0.5)
{
[self setFuelLeak:[NSString stringWithFormat:@"%f", (randf() + randf()) * 5.0]]; [self setFuelLeak:[NSString stringWithFormat:@"%f", (randf() + randf()) * 5.0]];
}
else else
{ {
[warningSound play]; [self playWitchjumpFailure];
[self takeInternalDamage]; [self takeInternalDamage];
} }
} }
@ -3865,8 +3871,7 @@ double scoopSoundPlayTime = 0.0;
galaxy_coordinates.y += target_system_seed.b; galaxy_coordinates.y += target_system_seed.b;
galaxy_coordinates.x /= 2; galaxy_coordinates.x /= 2;
galaxy_coordinates.y /= 2; galaxy_coordinates.y /= 2;
if (![UNIVERSE playCustomSound:@"[witchdrive-malfunction]"]) [self playWitchjumpMisjump];
[self playECMSound];
[UNIVERSE set_up_universe_from_misjump]; [UNIVERSE set_up_universe_from_misjump];
} }
} }
@ -3901,7 +3906,7 @@ double scoopSoundPlayTime = 0.0;
[UNIVERSE setDisplayCursor:NO]; [UNIVERSE setDisplayCursor:NO];
[UNIVERSE setDisplayText:NO]; [UNIVERSE setDisplayText:NO];
[UNIVERSE set_up_break_pattern:position quaternion:orientation]; [UNIVERSE set_up_break_pattern:position quaternion:orientation];
[self playBreakPattern]; [self playExitWitchspace];
[self doScriptEvent:@"shipWillExitWitchspace"]; [self doScriptEvent:@"shipWillExitWitchspace"];
} }

View File

@ -593,29 +593,7 @@ static NSTimeInterval time_last_frame;
{ {
if ([self fireMainWeapon]) if ([self fireMainWeapon])
{ {
if (target_laser_hit != NO_TARGET) [self playLaserHit:target_laser_hit != NO_TARGET];
{
if (weaponHitSound)
{
#if 0
// FIXME: should use an OOSoundSource.
if ([weaponHitSound isPlaying])
[weaponHitSound stop];
#endif
[weaponHitSound play];
}
}
else
{
if (weaponSound)
{
#if 0
// FIXME: should use an OOSoundSource.
if ([weaponSound isPlaying]) [weaponSound stop];
#endif
[weaponSound play];
}
}
} }
} }
@ -784,7 +762,7 @@ static NSTimeInterval time_last_frame;
{ {
if ([self fireECM]) if ([self fireECM])
{ {
[self playECMSound]; [self playFiredECMSound];
[UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[ecm-on]") forCount:3.0]; [UNIVERSE addMessage:ExpandDescriptionForCurrentSystem(@"[ecm-on]") forCount:3.0];
} }
} }
@ -2595,41 +2573,16 @@ static BOOL toggling_music;
gameView = [UNIVERSE gameView]; gameView = [UNIVERSE gameView];
if (([gameView isDown:gvFunctionKey1])||([gameView isDown:gvNumberKey1])) // look for the f1 key if (([gameView isDown:gvFunctionKey1])||([gameView isDown:gvNumberKey1])) // look for the f1 key
{ {
// ensure we've not left keyboard entry on // FIXME: should this not be in leaveDock:? (Note: leaveDock: is also called from script method launchFromStation and -[StationEntity becomeExplosion]) -- Ahruman 20080308
[gameView allowStringInput: NO];
if (gui_screen == GUI_SCREEN_MISSION) [self doScriptEvent:@"missionScreenEnded"];
[UNIVERSE setUpUniverseFromStation]; // launch! [UNIVERSE setUpUniverseFromStation]; // launch!
if (!dockedStation) if (!dockedStation) dockedStation = [UNIVERSE station];
dockedStation = [UNIVERSE station];
station = dockedStation; // leaveDock will clear dockedStation. station = dockedStation; // leaveDock will clear dockedStation.
//don't autosave immediately after a load //don't autosave immediately after a load
if (station == [UNIVERSE station] && [UNIVERSE autoSaveNow]) [self autosavePlayer]; if (station == [UNIVERSE station] && [UNIVERSE autoSaveNow]) [self autosavePlayer];
if ([UNIVERSE autoSave]) [UNIVERSE setAutoSaveNow:YES]; if ([UNIVERSE autoSave]) [UNIVERSE setAutoSaveNow:YES];
[self leaveDock:dockedStation]; [self leaveDock:dockedStation];
[UNIVERSE setDisplayCursor:NO];
suppressAegisMessages = YES;
#if 0
// "Fix" for "simple" issue where space compass shows station with planet icon on launch.
// Has the slight unwanted side-effect of effectively giving the player an advanced compass.
if ([self checkForAegis] != AEGIS_NONE)
{
[self setCompassMode:COMPASS_MODE_STATION];
}
else
{
[self setCompassMode:COMPASS_MODE_PLANET];
}
#else
[self checkForAegis];
#endif
suppressAegisMessages = NO;
ident_engaged = NO;
[self doScriptEvent:@"shipWillLaunchFromStation" withArgument:station];
[self playBreakPattern];
} }
} }

View File

@ -24,6 +24,7 @@ MA 02110-1301, USA.
#import "PlayerEntityLegacyScriptEngine.h" #import "PlayerEntityLegacyScriptEngine.h"
#import "PlayerEntityScriptMethods.h" #import "PlayerEntityScriptMethods.h"
#import "PlayerEntitySound.h"
#import "GuiDisplayGen.h" #import "GuiDisplayGen.h"
#import "Universe.h" #import "Universe.h"
#import "ResourceManager.h" #import "ResourceManager.h"
@ -2065,8 +2066,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
fuel_leak_rate = [value doubleValue]; fuel_leak_rate = [value doubleValue];
if (fuel_leak_rate > 0) if (fuel_leak_rate > 0)
{ {
if (![UNIVERSE playCustomSound:@"[fuel-leak]"]) [self playFuelLeak];
[self warnAboutHostiles];
[UNIVERSE addMessage:DESC(@"danger-fuel-leak") forCount:6]; [UNIVERSE addMessage:DESC(@"danger-fuel-leak") forCount:6];
OOLog(kOOLogNoteFuelLeak, @"FUEL LEAK activated!"); OOLog(kOOLogNoteFuelLeak, @"FUEL LEAK activated!");
} }
@ -2090,8 +2090,6 @@ static int scriptRandomSeed = -1; // ensure proper random function
- (void) launchFromStation - (void) launchFromStation
{ {
[self leaveDock:dockedStation]; [self leaveDock:dockedStation];
[UNIVERSE setDisplayCursor:NO];
[breakPatternSound play];
} }

View File

@ -36,20 +36,37 @@ enum
@interface PlayerEntity (Sound) @interface PlayerEntity (Sound)
- (void)setUpSound; - (void) setUpSound;
- (void)destroySound; - (void) destroySound;
- (void)beep; - (void) beep;
- (void)boop; - (void) boop;
- (void)playInterfaceBeep:(unsigned)inInterfaceBeep; - (void) playInterfaceBeep:(unsigned)inInterfaceBeep;
- (BOOL)isBeeping; - (BOOL) isBeeping;
- (void)playECMSound; - (void) playHitByECMSound;
- (void)stopECMSound; - (void) playFiredECMSound;
- (void)playBreakPattern; - (void) playLaunchFromStation;
- (void) playDockWithStation;
- (void) playExitWitchspace;
- (void)playHostileWarning; // Warning sounds
- (void)playAlertConditionRed; - (void) playHostileWarning;
- (void) playAlertConditionRed;
- (void) playIncomingMissile;
- (void) playEnergyLow;
- (void) playDockingDenied;
- (void) playWitchjumpFailure;
- (void) playWitchjumpMisjump;
- (void) playFuelLeak;
// Damage sounds
- (void) playShieldHit;
- (void) playDirectHit;
- (void) playScrapeDamage;
// Weapon sounds
- (void) playLaserHit:(BOOL)hit;
@end @end

View File

@ -25,6 +25,8 @@ MA 02110-1301, USA.
#import "PlayerEntitySound.h" #import "PlayerEntitySound.h"
#import "OOSound.h" #import "OOSound.h"
#import "ResourceManager.h" #import "ResourceManager.h"
#import "Universe.h"
#import "OOSoundSourcePool.h"
/* /*
@ -36,26 +38,32 @@ MA 02110-1301, USA.
#define BEEP_MODE 1 #define BEEP_MODE 1
// Sizes of sound source pools
enum
{
kWarningPoolSize = 2,
kWeaponPoolSize = 2,
kDamagePoolSize = 4
};
static OOSoundSourcePool *sWarningSoundPool;
static OOSoundSourcePool *sWeaponSoundPool;
static OOSoundSourcePool *sDamageSoundPool;
@implementation PlayerEntity (Sound) @implementation PlayerEntity (Sound)
- (void)setUpSound - (void) setUpSound
{ {
[self destroySound]; [self destroySound];
beepSound = [[ResourceManager ooSoundNamed:@"beep.ogg" inFolder:@"Sounds"] retain]; beepSound = [[ResourceManager ooSoundNamed:@"beep.ogg" inFolder:@"Sounds"] retain];
boopSound = [[ResourceManager ooSoundNamed:@"boop.ogg" inFolder:@"Sounds"] retain]; boopSound = [[ResourceManager ooSoundNamed:@"boop.ogg" inFolder:@"Sounds"] retain];
weaponSound = [[ResourceManager ooSoundNamed:@"laser.ogg" inFolder:@"Sounds"] retain];
weaponHitSound = [[ResourceManager ooSoundNamed:@"laserhits.ogg" inFolder:@"Sounds"] retain];
missileSound = [[ResourceManager ooSoundNamed:@"missile.ogg" inFolder:@"Sounds"] retain]; missileSound = [[ResourceManager ooSoundNamed:@"missile.ogg" inFolder:@"Sounds"] retain];
damageSound = [[ResourceManager ooSoundNamed:@"hit.ogg" inFolder:@"Sounds"] retain];
scrapeDamageSound = [[ResourceManager ooSoundNamed:@"hullbang.ogg" inFolder:@"Sounds"] retain];
destructionSound = [[ResourceManager ooSoundNamed:@"bigbang.ogg" inFolder:@"Sounds"] retain];
breakPatternSound = [[ResourceManager ooSoundNamed:@"breakpattern.ogg" inFolder:@"Sounds"] retain];
ecmSound = [[ResourceManager ooSoundNamed:@"ecm.ogg" inFolder:@"Sounds"] retain];
buySound = [[ResourceManager ooSoundNamed:@"buy.ogg" inFolder:@"Sounds"] retain]; buySound = [[ResourceManager ooSoundNamed:@"buy.ogg" inFolder:@"Sounds"] retain];
sellSound = [[ResourceManager ooSoundNamed:@"sell.ogg" inFolder:@"Sounds"] retain]; sellSound = [[ResourceManager ooSoundNamed:@"sell.ogg" inFolder:@"Sounds"] retain];
warningSound = [[ResourceManager ooSoundNamed:@"warning.ogg" inFolder:@"Sounds"] retain];
afterburner1Sound = [[ResourceManager ooSoundNamed:@"afterburner1.ogg" inFolder:@"Sounds"] retain]; afterburner1Sound = [[ResourceManager ooSoundNamed:@"afterburner1.ogg" inFolder:@"Sounds"] retain];
afterburner2Sound = [[ResourceManager ooSoundNamed:@"afterburner2.ogg" inFolder:@"Sounds"] retain]; afterburner2Sound = [[ResourceManager ooSoundNamed:@"afterburner2.ogg" inFolder:@"Sounds"] retain];
@ -67,36 +75,23 @@ MA 02110-1301, USA.
interfaceBeepSource = [[OOSoundSource alloc] init]; interfaceBeepSource = [[OOSoundSource alloc] init];
breakPatternSource = [[OOSoundSource alloc] init]; breakPatternSource = [[OOSoundSource alloc] init];
ecmSource = [[OOSoundSource alloc] init]; ecmSource = [[OOSoundSource alloc] init];
sWarningSoundPool = [[OOSoundSourcePool alloc] initWithCount:kWarningPoolSize minRepeatTime:0];
sWeaponSoundPool = [[OOSoundSourcePool alloc] initWithCount:kWeaponPoolSize minRepeatTime:0];
sDamageSoundPool = [[OOSoundSourcePool alloc] initWithCount:kDamagePoolSize minRepeatTime:0.1]; // Repeat time limit is to avoid playing a scrape sound every frame on glancing scrapes. This does limit the number of laser hits that can be played in a furrball, though; maybe lasers and scrapes should use different pools.
} }
- (void)destroySound - (void) destroySound
{ {
[beepSound release]; [beepSound release];
beepSound = nil; beepSound = nil;
[boopSound release]; [boopSound release];
boopSound = nil; boopSound = nil;
[weaponSound release];
weaponSound = nil;
[weaponHitSound release];
weaponHitSound = nil;
[damageSound release];
damageSound = nil;
[scrapeDamageSound release];
scrapeDamageSound = nil;
[destructionSound release];
destructionSound = nil;
[breakPatternSound release];
breakPatternSound = nil;
[ecmSound release];
ecmSound = nil;
[buySound release]; [buySound release];
buySound = nil; buySound = nil;
[sellSound release]; [sellSound release];
sellSound = nil; sellSound = nil;
[warningSound release];
warningSound = nil;
[afterburner1Sound release]; [afterburner1Sound release];
afterburner1Sound = nil; afterburner1Sound = nil;
[afterburner2Sound release]; [afterburner2Sound release];
@ -116,22 +111,29 @@ MA 02110-1301, USA.
ecmSource = nil; ecmSource = nil;
[breakPatternSource release]; [breakPatternSource release];
breakPatternSource = nil; breakPatternSource = nil;
[sWarningSoundPool release];
sWarningSoundPool = nil;
[sWeaponSoundPool release];
sWeaponSoundPool = nil;
[sDamageSoundPool release];
sDamageSoundPool = nil;
} }
- (void)beep - (void) beep
{ {
[self playInterfaceBeep:kInterfaceBeep_Beep]; [self playInterfaceBeep:kInterfaceBeep_Beep];
} }
- (void)boop - (void) boop
{ {
[self playInterfaceBeep:kInterfaceBeep_Boop]; [self playInterfaceBeep:kInterfaceBeep_Boop];
} }
- (void)playInterfaceBeep:(unsigned)inInterfaceBeep - (void) playInterfaceBeep:(unsigned)inInterfaceBeep
{ {
OOSound *sound = nil; OOSound *sound = nil;
@ -169,43 +171,118 @@ MA 02110-1301, USA.
} }
- (BOOL)isBeeping - (BOOL) isBeeping
{ {
return [interfaceBeepSource isPlaying]; return [interfaceBeepSource isPlaying];
} }
- (void)playECMSound - (void) playHitByECMSound
{ {
if (![ecmSource isPlaying]) [ecmSource playSound:ecmSound]; if (![ecmSource isPlaying]) [ecmSource playCustomSoundWithKey:@"[player-hit-by-ecm]"];
} }
- (void)stopECMSound - (void) playFiredECMSound
{ {
[ecmSource stop]; if (![ecmSource isPlaying]) [ecmSource playCustomSoundWithKey:@"[player-fired-ecm]"];
} }
- (void)playBreakPattern - (void) playLaunchFromStation
{ {
[breakPatternSource playSound:breakPatternSound]; [breakPatternSource playCustomSoundWithKey:@"[player-launch-from-station]"];
} }
- (void)playHostileWarning - (void) playDockWithStation
{ {
if (![warningSound isPlaying]) [warningSound play]; [breakPatternSource playCustomSoundWithKey:@"[player-dock-with-station]"];
} }
- (void)playAlertConditionRed - (void) playExitWitchspace
{ {
#if 0 [breakPatternSource playCustomSoundWithKey:@"[player-exit-witchspace]"];
// FIXME: should use an OOSoundSource. }
if ([warningSound isPlaying]) [warningSound stop];
#endif
[warningSound play]; - (void) playHostileWarning
{
[sWarningSoundPool playSoundWithKey:@"[hostile-warning]" priority:1];
}
- (void) playAlertConditionRed
{
[sWarningSoundPool playSoundWithKey:@"[alert-condition-red]" priority:2];
}
- (void) playIncomingMissile
{
[sWarningSoundPool playSoundWithKey:@"[incoming-missile]" priority:3];
}
- (void) playEnergyLow
{
[sWarningSoundPool playSoundWithKey:@"[energy-low]" priority:0.5];
}
- (void) playDockingDenied
{
[sWarningSoundPool playSoundWithKey:@"[autopilot-denied]" priority:1];
}
- (void) playWitchjumpFailure
{
[sWarningSoundPool playSoundWithKey:@"[witchdrive-failure]" priority:1.5];
}
- (void) playWitchjumpMisjump
{
[sWarningSoundPool playSoundWithKey:@"[witchdrive-malfunction]" priority:1.5];
}
- (void) playFuelLeak
{
[sWarningSoundPool playSoundWithKey:@"[fuel-leak]" priority:0.5];
}
- (void) playShieldHit
{
[sDamageSoundPool playSoundWithKey:@"[player-hit-by-weapon]"];
}
- (void) playDirectHit
{
[sDamageSoundPool playSoundWithKey:@"[player-direct-hit]"];
}
- (void) playScrapeDamage
{
[sDamageSoundPool playSoundWithKey:@"[player-scrape-damage]"];
}
- (void) playLaserHit:(BOOL)hit
{
if (hit)
{
[sWeaponSoundPool playSoundWithKey:@"[player-laser-hit]" priority:1 expiryTime:0.05];
}
else
{
[sWeaponSoundPool playSoundWithKey:@"[player-laser-miss]" priority:1 expiryTime:0.05];
}
} }
@end @end

View File

@ -293,7 +293,7 @@ MA 02110-1301, USA.
NSMutableArray *subEntities; NSMutableArray *subEntities;
@private @private
OOWeakReference *subEntityTakingDamage; // frangible => subEntities can be damaged individually OOWeakReference *_subEntityTakingDamage; // frangible => subEntities can be damaged individually
} }
// ship brains // ship brains

View File

@ -465,7 +465,7 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
[octree autorelease]; [octree autorelease];
[subEntityTakingDamage release]; [self setSubEntityTakingDamage:nil];
[super dealloc]; [super dealloc];
} }
@ -556,26 +556,16 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
- (ShipEntity *) subEntityTakingDamage - (ShipEntity *) subEntityTakingDamage
{ {
ShipEntity *result = [subEntityTakingDamage weakRefUnderlyingObject]; ShipEntity *result = [_subEntityTakingDamage weakRefUnderlyingObject];
#ifndef NDEBUG #ifndef NDEBUG
// Sanity check - there have been problems here, see fireLaserShotInDirection: // Sanity check - there have been problems here, see fireLaserShotInDirection:
if (result != nil) // -parentEntity will take care of reporting insanity.
{ if ([result parentEntity] != self) result = nil;
if (![result isShip] || ![self hasSubEntity:result])
{
OOLog(@"ship.subentity.sanityCheck.failed", @"***** VALIDATION ERROR: Subentity taking damage (%@) for ship %@ is not a ship or is not a subentity of the owner. This is an internal error, please report it.", [result shortDescription], [self shortDescription]);
result = nil;
}
}
#endif #endif
// Clear the weakref if the subentity is dead // Clear the weakref if the subentity is dead.
if (result == nil) if (result == nil) [self setSubEntityTakingDamage:nil];
{
[subEntityTakingDamage release];
subEntityTakingDamage = nil;
}
return result; return result;
} }
@ -583,12 +573,25 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
- (void) setSubEntityTakingDamage:(ShipEntity *)sub - (void) setSubEntityTakingDamage:(ShipEntity *)sub
{ {
// Set subentityTakingDamage only if sub is 1. one of ours and 2. a ship (not a flasher or exhaust). #ifndef NDEBUG
if ([sub isShip] && [self hasSubEntity:sub]) // Sanity checks: sub must be a ship subentity of self, or nil.
if (sub != nil)
{ {
[subEntityTakingDamage release]; if (![self hasSubEntity:sub])
subEntityTakingDamage = [sub weakRetain]; {
OOLog(@"ship.subentity.sanityCheck.failed.deatails", @"Attempt to set subentity taking damage of %@ to %@, which is not a subentity.", [self shortDescription], sub);
sub = nil;
}
if (![sub isShip])
{
OOLog(@"ship.subentity.sanityCheck.failed", @"Attempt to set subentity taking damage of %@ to %@, which is not a ship.", [self shortDescription], sub);
sub = nil;
}
} }
#endif
[_subEntityTakingDamage release];
_subEntityTakingDamage = [sub weakRetain];
} }
@ -4023,11 +4026,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
- (void)subEntityDied:(ShipEntity *)sub - (void)subEntityDied:(ShipEntity *)sub
{ {
if ([subEntityTakingDamage weakRefUnderlyingObject] == sub) if ([self subEntityTakingDamage] == sub) [self setSubEntityTakingDamage:nil];
{
[subEntityTakingDamage release];
subEntityTakingDamage = nil;
}
[sub setOwner:nil]; [sub setOwner:nil];
[subEntities removeObject:sub]; [subEntities removeObject:sub];
@ -4040,11 +4039,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
unsigned i, count; unsigned i, count;
id element; id element;
if ([subEntityTakingDamage weakRefUnderlyingObject] == sub) if ([self subEntityTakingDamage] == sub) [self setSubEntityTakingDamage:nil];
{
[subEntityTakingDamage release];
subEntityTakingDamage = nil;
}
if ([self hasSubEntity:sub]) if ([self hasSubEntity:sub])
{ {

View File

@ -59,8 +59,6 @@ SOFTWARE.
@interface OOShaderProgram: NSObject @interface OOShaderProgram: NSObject
{ {
GLhandleARB program; GLhandleARB program;
GLhandleARB vertexShader;
GLhandleARB fragmentShader;
NSString *key; NSString *key;
} }

View File

@ -120,11 +120,13 @@ static NSString *GetGLSLInfoLog(GLhandleARB shaderObject);
{ {
OO_ENTER_OPENGL(); OO_ENTER_OPENGL();
#ifndef NDEBUG
if (EXPECT_NOT(sActiveProgram == self)) if (EXPECT_NOT(sActiveProgram == self))
{ {
OOLog(@"shader.dealloc.imbalance", @"***** OOShaderProgram deallocated while active, indicating a retain/release imbalance. Expect imminent crash."); OOLog(@"shader.dealloc.imbalance", @"***** OOShaderProgram deallocated while active, indicating a retain/release imbalance. Expect imminent crash.");
[OOShaderProgram applyNone]; [OOShaderProgram applyNone];
} }
#endif
if (key != nil) if (key != nil)
{ {
@ -133,8 +135,6 @@ static NSString *GetGLSLInfoLog(GLhandleARB shaderObject);
} }
glDeleteObjectARB(program); glDeleteObjectARB(program);
glDeleteObjectARB(vertexShader);
glDeleteObjectARB(fragmentShader);
[super dealloc]; [super dealloc];
} }
@ -185,6 +185,8 @@ static NSString *GetGLSLInfoLog(GLhandleARB shaderObject);
BOOL OK = YES; BOOL OK = YES;
const GLcharARB *sourceString = NULL; const GLcharARB *sourceString = NULL;
GLint compileStatus; GLint compileStatus;
GLhandleARB vertexShader;
GLhandleARB fragmentShader;
OO_ENTER_OPENGL(); OO_ENTER_OPENGL();
@ -258,11 +260,12 @@ static NSString *GetGLSLInfoLog(GLhandleARB shaderObject);
key = [inKey copy]; key = [inKey copy];
} }
if (vertexShader != NULL) glDeleteObjectARB(vertexShader);
if (fragmentShader != NULL) glDeleteObjectARB(fragmentShader);
if (!OK) if (!OK)
{ {
if (vertexShader) glDeleteObjectARB(vertexShader); if (program != NULL) glDeleteObjectARB(program);
if (fragmentShader) glDeleteObjectARB(fragmentShader);
if (program) glDeleteObjectARB(program);
[self release]; [self release];
self = nil; self = nil;

View File

@ -187,7 +187,7 @@ static unsigned sCacheMisses = 0;
NSEnumerator *substEnum = nil; NSEnumerator *substEnum = nil;
NSMutableString *mutable = nil; NSMutableString *mutable = nil;
mutable = [string mutableCopy]; mutable = [[string mutableCopy] autorelease];
if (mutable == nil) return nil; if (mutable == nil) return nil;
for (substEnum = [_substitutions keyEnumerator]; (subst = [substEnum nextObject]); ) for (substEnum = [_substitutions keyEnumerator]; (subst = [substEnum nextObject]); )

View File

@ -43,10 +43,12 @@ BOOL CheckOpenGLErrors(NSString *format, ...)
// Short-circut here, because glGetError() is quite expensive. // Short-circut here, because glGetError() is quite expensive.
if (OOLogWillDisplayMessagesInClass(kOOLogOpenGLError)) if (OOLogWillDisplayMessagesInClass(kOOLogOpenGLError))
{ {
errCode = glGetError(); for (;;)
if (errCode != GL_NO_ERROR)
{ {
errCode = glGetError();
if (errCode == GL_NO_ERROR) break;
errorOccurred = YES; errorOccurred = YES;
errString = gluErrorString(errCode); errString = gluErrorString(errCode);
if (format == nil) format = @"<unknown>"; if (format == nil) format = @"<unknown>";

View File

@ -41,7 +41,7 @@ MA 02110-1301, USA.
*/ */
#if defined(LINUX) || defined(OOLITE_SDL_MAC) #if OOLITE_SDL
#import "SDLSound.h" #import "SDLSound.h"
#import "SDLMusic.h" #import "SDLMusic.h"
#import "OOBasicSoundSource.h" #import "OOBasicSoundSource.h"

View File

@ -0,0 +1,83 @@
/*
OOSoundSourcePool.h
Manages a fixed number of sound sources and distributes sounds between them.
Each sound has a priority and an expiry time. When a new sound is played, it
replaces (if possible) a sound of lower priority that has expired, a sound of
the same priority that has expired, or a sound of lower priority that has not
expired.
All sounds are specified by customsounds.plist key.
Oolite
Copyright (C) 2004-2008 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
This file may also be distributed under the MIT/X11 license:
Copyright (C) 2008 Jens Ayton
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "OOTypes.h"
@interface OOSoundSourcePool: NSObject
{
struct OOSoundSourcePoolElement *_sources;
uint8_t _count;
uint8_t _latest;
OOTimeDelta _minRepeat;
OOTimeAbsolute _nextRepeat;
NSString *_lastKey;
}
+ (id) poolWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat;
- (id) initWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat;
- (void) playSoundWithKey:(NSString *)key
priority:(float)priority
expiryTime:(OOTimeDelta)expiryTime;
- (void) playSoundWithKey:(NSString *)key
priority:(float)priority; // expiryTime:0.1 +/- 0.5
- (void) playSoundWithKey:(NSString *)key; // priority: 1.0, expiryTime:0.1 +/- 0.5
@end

View File

@ -0,0 +1,221 @@
/*
OOSoundSourcePool.m
Oolite
Copyright (C) 2004-2008 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
This file may also be distributed under the MIT/X11 license:
Copyright (C) 2008 Jens Ayton
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#import "OOSoundSourcePool.h"
#import "OOSound.h"
#import "Universe.h"
enum
{
kNoSlot = UINT8_MAX
};
typedef struct OOSoundSourcePoolElement
{
OOSoundSource *source;
OOTimeAbsolute expiryTime;
float priority;
} PoolElement;
@interface OOSoundSourcePool (Private)
- (uint8_t) selectSlotForPriority:(float)priority;
@end
@implementation OOSoundSourcePool
+ (id) poolWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat
{
return [[[self alloc] initWithCount:count minRepeatTime:minRepeat] autorelease];
}
- (id) initWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat
{
if ((self = [super init]))
{
// Sanity-check count
if (count == 0) count = 1;
if (count == kNoSlot) --count;
_count = count;
if (minRepeat < 0.0) minRepeat = 0.0;
_minRepeat = minRepeat;
// Create source pool
_sources = calloc(sizeof(PoolElement), count);
if (_sources == NULL)
{
[self release];
self = nil;
}
}
return self;
}
- (void) dealloc
{
uint8_t i;
for (i = 0; i != _count; i++)
{
[_sources[i].source release];
}
[_lastKey release];
[super dealloc];
}
- (void) playSoundWithKey:(NSString *)key
priority:(float)priority
expiryTime:(OOTimeDelta)expiryTime
{
uint8_t slot;
OOTimeAbsolute now, absExpiryTime;
PoolElement *element = NULL;
OOSound *sound = NULL;
// Convert expiry time to absolute
now = [UNIVERSE getTime];
absExpiryTime = expiryTime + now;
// Avoid repeats if required
if (now < _nextRepeat && [key isEqualToString:_lastKey]) return;
// Look for a slot in the source list to use
slot = [self selectSlotForPriority:priority];
if (slot == kNoSlot) return;
element = &_sources[slot];
// Load sound
sound = [OOSound soundWithCustomSoundKey:key];
if (sound == nil) return;
// Stop playing sound or set up sound source as appropriate
if (element->source != nil) [element->source stop];
else
{
element->source = [[OOSoundSource alloc] init];
if (element->source == nil) return;
}
// Play and store metadata
[element->source playSound:sound];
element->expiryTime = absExpiryTime;
element->priority = priority;
if (_minRepeat > 0.0)
{
_nextRepeat = now + _minRepeat;
[_lastKey release];
_lastKey = [key copy];
}
// Set staring search location for next slot lookup
_latest = slot;
}
- (void) playSoundWithKey:(NSString *)key
priority:(float)priority
{
[self playSoundWithKey:key
priority:priority
expiryTime:0.5 + randf() * 0.1];
}
- (void) playSoundWithKey:(NSString *)key
{
[self playSoundWithKey:key priority:1.0];
}
@end
@implementation OOSoundSourcePool (Private)
- (uint8_t) selectSlotForPriority:(float)priority
{
uint8_t curr, count, expiredLower = kNoSlot, unexpiredLower = kNoSlot, expiredEqual = kNoSlot;
PoolElement *element = NULL;
OOTimeAbsolute now = [UNIVERSE getTime];
#define NEXT(x) (((x) + 1) % _count)
curr = _latest;
count = _count;
do
{
curr = NEXT(curr);
element = &_sources[curr];
if (element->source == nil || ![element->source isPlaying]) return curr; // Best type of slot: empty
else if (element->priority < priority)
{
if (element->expiryTime <= now) expiredLower = curr; // Second-best type: expired lower-priority
else unexpiredLower = curr; // Third-best type: unexpired lower-priority
}
else if (element->priority == priority && element->expiryTime <= now)
{
expiredEqual = curr; // Fourth-best type: expired equal-priority.
}
} while (--count);
if (expiredLower != kNoSlot) return expiredLower;
if (unexpiredLower != kNoSlot) return unexpiredLower;
return expiredEqual; // Will be kNoSlot if none found
}
@end

View File

@ -518,7 +518,7 @@ static NSMutableDictionary *string_cache;
NSEnumerator *enumerator = nil; NSEnumerator *enumerator = nil;
NSString *path = nil; NSString *path = nil;
NSString *arrayPath = nil; NSString *arrayPath = nil;
NSMutableArray *array = nil; NSMutableArray *array = nil;
NSArray *arrayNonEditable = nil; NSArray *arrayNonEditable = nil;
if (fileName == nil) return nil; if (fileName == nil) return nil;
@ -551,8 +551,7 @@ static NSMutableDictionary *string_cache;
for (enumerator = [ResourceManager pathEnumerator]; (path = [enumerator nextObject]); ) for (enumerator = [ResourceManager pathEnumerator]; (path = [enumerator nextObject]); )
{ {
arrayPath = [path stringByAppendingPathComponent:fileName]; arrayPath = [path stringByAppendingPathComponent:fileName];
[array release]; array = [[OOArrayFromFile(arrayPath) mutableCopy] autorelease];
array = [OOArrayFromFile(arrayPath) mutableCopy];
if (array != nil) [results addObject:array]; if (array != nil) [results addObject:array];
// Special handling for arrays merging. Currently, equipment.plist only gets its objects merged. // Special handling for arrays merging. Currently, equipment.plist only gets its objects merged.
@ -566,8 +565,7 @@ static NSMutableDictionary *string_cache;
if (folderName != nil) if (folderName != nil)
{ {
arrayPath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName]; arrayPath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
[array release]; array = [[OOArrayFromFile(arrayPath) mutableCopy] autorelease];
array = [OOArrayFromFile(arrayPath) mutableCopy];
if (array != nil) [results addObject:array]; if (array != nil) [results addObject:array];
if (array != nil && [[array objectAtIndex:0] isKindOfClass:[NSArray class]]) if (array != nil && [[array objectAtIndex:0] isKindOfClass:[NSArray class]])

View File

@ -29,7 +29,7 @@ MA 02110-1301, USA.
@interface OOJSScript: OOScript <OOWeakReferenceSupport> @interface OOJSScript: OOScript <OOWeakReferenceSupport>
{ {
JSObject *object; JSObject *_jsSelf;
NSString *name; NSString *name;
NSString *description; NSString *description;

View File

@ -130,18 +130,18 @@ static JSFunctionSpec sScriptMethods[] =
if (!problem) if (!problem)
{ {
// Do we actually want parent to be the global object here? // Do we actually want parent to be the global object here?
object = JS_NewObject(context, &sScriptClass, sScriptPrototype, NULL /*JS_GetGlobalObject(context)*/); _jsSelf = JS_NewObject(context, &sScriptClass, sScriptPrototype, NULL /*JS_GetGlobalObject(context)*/);
if (object == NULL) problem = @"allocation failure"; if (_jsSelf == NULL) problem = @"allocation failure";
} }
if (!problem) if (!problem)
{ {
if (!JS_SetPrivate(context, object, [self weakRetain])) problem = @"could not set private backreference"; if (!JS_SetPrivate(context, _jsSelf, [self weakRetain])) problem = @"could not set private backreference";
} }
if (!problem) if (!problem)
{ {
if (![engine addGCRoot:&object named:"Script object"]) if (![engine addGCRoot:&_jsSelf named:"Script object"])
{ {
problem = @"could not add JavaScript root object"; problem = @"could not add JavaScript root object";
} }
@ -149,7 +149,7 @@ static JSFunctionSpec sScriptMethods[] =
if (!problem) if (!problem)
{ {
script = LoadScriptWithName(context, path, object, &problem); script = LoadScriptWithName(context, path, _jsSelf, &problem);
} }
// Set properties. // Set properties.
@ -168,7 +168,7 @@ static JSFunctionSpec sScriptMethods[] =
// Run the script (allowing it to set up the properties we need, as well as setting up those event handlers) // Run the script (allowing it to set up the properties we need, as well as setting up those event handlers)
if (!problem) if (!problem)
{ {
if (!JS_ExecuteScript(context, object, script, &returnValue)) if (!JS_ExecuteScript(context, _jsSelf, script, &returnValue))
{ {
problem = @"could not run script"; problem = @"could not run script";
} }
@ -211,9 +211,13 @@ static JSFunctionSpec sScriptMethods[] =
[name release]; [name release];
[description release]; [description release];
[version release]; [version release];
[weakSelf weakRefDrop];
[[OOJavaScriptEngine sharedEngine] removeGCRoot:&object]; JSContext *context = [[OOJavaScriptEngine sharedEngine] acquireContext];
JSObjectWrapperFinalize(context, _jsSelf); // Release weakref to self
JS_RemoveRoot(context, &_jsSelf); // Unroot jsSelf
[[OOJavaScriptEngine sharedEngine] releaseContext:context];
[weakSelf weakRefDrop];
[super dealloc]; [super dealloc];
} }
@ -290,7 +294,7 @@ static JSFunctionSpec sScriptMethods[] =
jsval value; jsval value;
JSFunction *function = NULL; JSFunction *function = NULL;
OK = JS_GetProperty(context, object, [eventName UTF8String], &value); OK = JS_GetProperty(context, _jsSelf, [eventName UTF8String], &value);
#if SUPPORT_CHANGED_HANDLERS #if SUPPORT_CHANGED_HANDLERS
if (!OK || value == JSVAL_VOID) if (!OK || value == JSVAL_VOID)
@ -317,7 +321,7 @@ static JSFunctionSpec sScriptMethods[] =
{ {
for (oldNameEnum = [oldNames objectEnumerator]; (oldName = [oldNameEnum nextObject]) && value == JSVAL_VOID && OK; ) for (oldNameEnum = [oldNames objectEnumerator]; (oldName = [oldNameEnum nextObject]) && value == JSVAL_VOID && OK; )
{ {
OK = JS_GetProperty(context, object, [oldName UTF8String], &value); OK = JS_GetProperty(context, _jsSelf, [oldName UTF8String], &value);
if (OK && value != JSVAL_VOID) if (OK && value != JSVAL_VOID)
{ {
@ -380,7 +384,7 @@ static JSFunctionSpec sScriptMethods[] =
} }
// Actually call the function // Actually call the function
OK = JS_CallFunction(context, object, function, argc, argv, &value); OK = JS_CallFunction(context, _jsSelf, function, argc, argv, &value);
// Re-garbage-collectibalize the arguments and free the array // Re-garbage-collectibalize the arguments and free the array
if (argv != NULL) if (argv != NULL)
@ -424,7 +428,7 @@ static JSFunctionSpec sScriptMethods[] =
if (propName == nil) return nil; if (propName == nil) return nil;
context = [[OOJavaScriptEngine sharedEngine] acquireContext]; context = [[OOJavaScriptEngine sharedEngine] acquireContext];
OK = JSGetNSProperty(NULL, object, propName, &value); OK = JSGetNSProperty(NULL, _jsSelf, propName, &value);
if (OK && !JSVAL_IS_VOID(value)) result = JSValueToObject(context, value); if (OK && !JSVAL_IS_VOID(value)) result = JSValueToObject(context, value);
[[OOJavaScriptEngine sharedEngine] releaseContext:context]; [[OOJavaScriptEngine sharedEngine] releaseContext:context];
@ -444,7 +448,7 @@ static JSFunctionSpec sScriptMethods[] =
jsValue = [value javaScriptValueInContext:context]; jsValue = [value javaScriptValueInContext:context];
if (!JSVAL_IS_VOID(jsValue)) if (!JSVAL_IS_VOID(jsValue))
{ {
result = JSDefineNSProperty(context, object, propName, jsValue, NULL, NULL, JSPROP_ENUMERATE); result = JSDefineNSProperty(context, _jsSelf, propName, jsValue, NULL, NULL, JSPROP_ENUMERATE);
} }
[[OOJavaScriptEngine sharedEngine] releaseContext:context]; [[OOJavaScriptEngine sharedEngine] releaseContext:context];
return result; return result;
@ -463,7 +467,7 @@ static JSFunctionSpec sScriptMethods[] =
jsValue = [value javaScriptValueInContext:context]; jsValue = [value javaScriptValueInContext:context];
if (!JSVAL_IS_VOID(jsValue)) if (!JSVAL_IS_VOID(jsValue))
{ {
result = JSDefineNSProperty(context, object, propName, jsValue, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); result = JSDefineNSProperty(context, _jsSelf, propName, jsValue, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
} }
[[OOJavaScriptEngine sharedEngine] releaseContext:context]; [[OOJavaScriptEngine sharedEngine] releaseContext:context];
return result; return result;
@ -472,7 +476,7 @@ static JSFunctionSpec sScriptMethods[] =
- (jsval)javaScriptValueInContext:(JSContext *)context - (jsval)javaScriptValueInContext:(JSContext *)context
{ {
return OBJECT_TO_JSVAL(object); return OBJECT_TO_JSVAL(_jsSelf);
} }

View File

@ -31,6 +31,7 @@ MA 02110-1301, USA.
#import "OOColor.h" #import "OOColor.h"
#import "OOWeakReference.h" #import "OOWeakReference.h"
#import "OOTypes.h" #import "OOTypes.h"
#import "OOSound.h"
@class GameController, CollisionRegion, MyOpenGLView, GuiDisplayGen, @class GameController, CollisionRegion, MyOpenGLView, GuiDisplayGen,
Entity, ShipEntity, StationEntity, PlanetEntity, PlayerEntity, Entity, ShipEntity, StationEntity, PlanetEntity, PlayerEntity,
@ -121,7 +122,7 @@ enum
#define BILLBOARD_DEPTH 50000.0 #define BILLBOARD_DEPTH 50000.0
@interface Universe: NSObject <OOWeakReferenceSupport> @interface Universe: OOWeakRefObject
{ {
@public @public
// use a sorted list for drawing and other activities // use a sorted list for drawing and other activities
@ -243,8 +244,6 @@ enum
NSMutableArray *entitiesDeadThisUpdate; NSMutableArray *entitiesDeadThisUpdate;
OOWeakReference *weakSelf;
#if OOLITE_MAC_OS_X #if OOLITE_MAC_OS_X
NSSpeechSynthesizer *speechSynthesizer; // use this from OS X 10.3 onwards NSSpeechSynthesizer *speechSynthesizer; // use this from OS X 10.3 onwards
NSArray *speechArray; NSArray *speechArray;
@ -409,7 +408,8 @@ enum
- (void) setViewDirection:(OOViewID) vd; - (void) setViewDirection:(OOViewID) vd;
- (OOViewID) viewDirection; - (OOViewID) viewDirection;
- (BOOL) playCustomSound:(NSString*)key; - (BOOL) playCustomSound:(NSString*)key; // DEPRECATED -- use +[OOSound soundWithCustomSoundKey:] and OOSoundSource.
- (NSString *) soundNameForCustomSoundKey:(NSString *)key;
- (void) clearPreviousMessage; - (void) clearPreviousMessage;
- (void) setMessageGuiBackgroundColor:(OOColor *) some_color; - (void) setMessageGuiBackgroundColor:(OOColor *) some_color;
@ -575,3 +575,21 @@ OOINLINE Universe *GetUniverse(void)
#define DESC(key) ([UNIVERSE descriptionForKey:(key "")]) // Only for use with string literals, and only for looking up strings. #define DESC(key) ([UNIVERSE descriptionForKey:(key "")]) // Only for use with string literals, and only for looking up strings.
@interface OOSound (OOCustomSounds)
+ (id) soundWithCustomSoundKey:(NSString *)key;
- (id) initWithCustomSoundKey:(NSString *)key;
@end
@interface OOSoundSource (OOCustomSounds)
+ (id) sourceWithCustomSoundKey:(NSString *)key;
- (id) initWithCustomSoundKey:(NSString *)key;
- (void) playCustomSoundWithKey:(NSString *)key;
@end

View File

@ -320,8 +320,6 @@ static NSComparisonResult comparePrice(NSDictionary *dict1, NSDictionary *dict2,
[[OOCacheManager sharedCache] flush]; [[OOCacheManager sharedCache] flush];
[weakSelf weakRefDrop];
#ifndef OOLITE_MAC_OS_X #ifndef OOLITE_MAC_OS_X
[speechArray release]; [speechArray release];
[speechSynthesizer release]; [speechSynthesizer release];
@ -331,19 +329,6 @@ static NSComparisonResult comparePrice(NSDictionary *dict1, NSDictionary *dict2,
} }
- (id)weakRetain
{
if (weakSelf == nil) weakSelf = [OOWeakReference weakRefWithObject:self];
return [weakSelf retain];
}
- (void)weakRefDied:(OOWeakReference *)weakRef
{
if (weakRef == weakSelf) weakSelf = nil;
}
#ifdef ALLOW_PROCEDURAL_PLANETS #ifdef ALLOW_PROCEDURAL_PLANETS
- (BOOL) doProcedurallyTexturedPlanets - (BOOL) doProcedurallyTexturedPlanets
{ {
@ -4920,20 +4905,19 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
} }
- (NSString *) soundNameForCustomSoundKey:(NSString *)key;
{
return [customsounds stringForKey:key];
}
- (BOOL) playCustomSound:(NSString*)key - (BOOL) playCustomSound:(NSString*)key
{ {
NSString *fileName = nil; OOSound* sound = [OOSound soundWithCustomSoundKey:key];
if (sound)
fileName = [customsounds stringForKey:key];
if (fileName != nil)
{ {
OOSound* sound = [ResourceManager ooSoundNamed:fileName inFolder:@"Sounds"]; [sound play];
if (sound) return YES;
{
if (![sound isPlaying])
[sound play];
return YES;
}
} }
return NO; return NO;
} }
@ -7955,3 +7939,55 @@ static NSComparisonResult comparePrice(NSDictionary *dict1, NSDictionary *dict2,
} }
@end @end
@implementation OOSound (OOCustomSounds)
+ (id) soundWithCustomSoundKey:(NSString *)key
{
NSString *fileName = [UNIVERSE soundNameForCustomSoundKey:key];
if (fileName == nil) return nil;
return [ResourceManager ooSoundNamed:fileName inFolder:@"Sounds"];
}
- (id) initWithCustomSoundKey:(NSString *)key
{
[self release];
return [[[self class] soundWithCustomSoundKey:key] retain];
}
@end
@implementation OOSoundSource (OOCustomSounds)
+ (id) sourceWithCustomSoundKey:(NSString *)key
{
return [[[self alloc] initWithCustomSoundKey:key] autorelease];
}
- (id) initWithCustomSoundKey:(NSString *)key
{
OOSound *theSound = [OOSound soundWithCustomSoundKey:key];
if (theSound != nil)
{
self = [self initWithSound:theSound];
}
else
{
[self release];
self = nil;
}
return self;
}
- (void) playCustomSoundWithKey:(NSString *)key
{
OOSound *theSound = [OOSound soundWithCustomSoundKey:key];
if (theSound != nil) [self playSound:theSound];
}
@end