Code: Select all
; ID: 2975
; Author: RifRaf, further modified by MonocleBios
; Date: 2012-09-11 11:44:22
; Title: Safe Loads (b3d) ;strict loads sounds more appropriate IMO
; Description: Get the missing filename reported
;safe loads for mav trapping media issues
;basic wrapper functions that check to make sure that the file exists before attempting to load it, raises an RTE if it doesn't
;more informative alternative to MAVs outside of debug mode, makes it immiediately obvious whether or not someone is loading resources
;likely to cause more crashes than 'clean' CB, as this prevents anyone from loading any assets that don't exist, regardless if they are ever used
;added zero checks since blitz load functions return zero sometimes even if the filetype exists
;sounds are automatically released from memory to prevent any issues regarding having too many sounds loaded at once
Type Sound
Field internalHandle%
Field name$
Field channels%[32]
Field releaseTime%
End Type
Function LoadImage_Strict(file$)
If FileType(file$)<>1 Then RuntimeError "Image " + file$ + " missing. "
tmp = LoadImage(file$)
If tmp = 0 Then RuntimeError "Failed to load Image: " + file$
Return tmp
End Function
Function AutoReleaseSounds()
Local snd.Sound
For snd.Sound = Each Sound
Local tryRelease% = True
For i=0 To 31
If snd\channels[i]<>0 Then
If ChannelPlaying(snd\channels[i]) Then
tryRelease = False
snd\releaseTime = MilliSecs()+5000
Exit
EndIf
EndIf
Next
If tryRelease Then
If snd\releaseTime<MilliSecs() Then
If snd\internalHandle<>0 Then
FreeSound snd\internalHandle
snd\internalHandle = 0
DebugLog "RELEASED "+snd\name
EndIf
EndIf
EndIf
Next
End Function
Function PlaySound_Strict%(sndHandle%)
Local snd.Sound = Object.Sound(sndHandle)
If snd<>Null Then
Local shouldPlay% = True
For i=0 To 31
If snd\channels[i]<>0 Then
If Not ChannelPlaying(snd\channels[i]) Then
If snd\internalHandle=0 Then
If FileType(snd\name)<>1 Then
RuntimeError "Sound " +snd\name+ " not found."
EndIf
snd\internalHandle = LoadSound(snd\name)
If snd\internalHandle = 0 Then
RuntimeError "Failed to load Sound:" +snd\name
EndIf
EndIf
snd\channels[i]=PlaySound(snd\internalHandle)
snd\releaseTime = MilliSecs()+5000 ;release after 5 seconds
Return snd\channels[i]
EndIf
Else
If snd\internalHandle=0 Then
If FileType(snd\name)<>1 Then
RuntimeError "Sound " +snd\name+ " not found."
EndIf
snd\internalHandle = LoadSound(snd\name)
If snd\internalHandle = 0 Then
RuntimeError "Failed to load Sound:" +snd\name
EndIf
EndIf
snd\channels[i]=PlaySound(snd\internalHandle)
snd\releaseTime = MilliSecs()+5000 ;release after 5 seconds
Return snd\channels[i]
EndIf
Next
Else
RuntimeError "Tried playing null sound!"
EndIf
Return 0
End Function
Function LoadSound_Strict(file$)
Local snd.Sound = New Sound
snd\name = file
snd\internalHandle = 0
snd\releaseTime = 0
Return Handle(snd)
End Function
Function FreeSound_Strict(sndHandle%)
Local snd.Sound = Object.Sound(sndHandle)
If snd<>Null Then
If snd\internalHandle<>0 Then
FreeSound snd\internalHandle
snd\internalHandle = 0
EndIf
Delete snd
Else
RuntimeError "Tried freeing null sound!"
EndIf
End Function
Function LoadMesh_Strict(File$,parent=0)
If FileType(File$)<>1 Then RuntimeError "3D Mesh " + File$ + " not found."
tmp = LoadMesh(File$, parent)
If tmp = 0 Then RuntimeError "Failed to load 3D Mesh: " + File$
Return tmp
End Function
Function LoadAnimMesh_Strict(File$,parent=0)
DebugLog File
If FileType(File$)<>1 Then RuntimeError "3D Animated Mesh " + File$ + " not found."
tmp = LoadAnimMesh(File$, parent)
If tmp = 0 Then RuntimeError "Failed to load 3D Animated Mesh: " + File$
Return tmp
End Function
;don't use in LoadRMesh, as Reg does this manually there. If you wanna fuck around with the logic in that function, be my guest
Function LoadTexture_Strict(File$,flags=1)
If FileType(File$)<>1 Then RuntimeError "Texture " + File$ + " not found."
tmp = LoadTexture(File$, flags)
If tmp = 0 Then RuntimeError "Failed to load Texture: " + File$
Return tmp
End Function
Function LoadBrush_Strict(file$,flags,u#=1.0,v#=1.0)
If FileType(file$)<>1 Then RuntimeError "Brush Texture " + file$ + "not found."
tmp = LoadBrush(file$, flags, u, v)
If tmp = 0 Then RuntimeError "Failed to load Brush: " + file$
Return tmp
End Function
;Modified for Fasttext
Function LoadFont_Strict(file$="Tahoma", height=13, bold=0, italic=0, underline=0, angle#=0, smooth=FT_ANTIALIASED, encoding=FT_ASCII)
If FileType(file$)<>1 Then RuntimeError "Font " + file$ + " not found."
tmp = LoadFont(file, height, bold, italic, underline, angle, smooth, encoding)
If tmp = 0 Then RuntimeError "Failed to load Font: " + file$
Return tmp
End Function
This code adds a function that automatically releases any sounds that haven't been playing in the last five seconds, and reloads them if the game needs them again. This might cause some performance drops, but it's the easiest fix I could think of.
To use it, replace StrictLoads.bb with this code, replace all calls of PlaySound with PlaySound_Strict, all calls of FreeSound with FreeSound_Strict, all calls of LoadSound with LoadSound_Strict, and call AutoReleaseSounds somewhere in the main loop.
This fix isn't effective if you noclip through ten different events and trigger them all in less than 5 seconds.
Also, I found that in the Class-D/Scientist code, the game tries to play sounds that are never loaded:
Code: Select all
If prevFrame < 244 And AnimTime(n\obj)=>244 Then
PlaySound2(StepSFX(2,0,Rand(0,2)),Camera, n\Collider, 8.0, Rnd(0.3,0.5))
ElseIf prevFrame < 256 And AnimTime(n\obj)=>256
PlaySound2(StepSFX(2,0,Rand(0,2)),Camera, n\Collider, 8.0, Rnd(0.3,0.5))
ElseIf prevFrame < 309 And AnimTime(n\obj)=>309
PlaySound2(StepSFX(2,1,Rand(0,2)),Camera, n\Collider, 8.0, Rnd(0.3,0.5)) ;<---- this points to null sounds
ElseIf prevFrame =< 319 And AnimTime(n\obj)=<301
PlaySound2(StepSFX(2,1,Rand(0,2)),Camera, n\Collider, 8.0, Rnd(0.3,0.5)) ;<---- this points to null sounds
EndIf