Updated script:
#Conditional Hooks
$Application: Freespace 2
$On Game Init: [
--Function to handle a section every frame
section = function(name, event, num)
--MENU COLOR
local xmargin = gr.getScreenWidth()/8
local ymargin = gr.getScreenHeight()/8
--Get corner coordinates for this box
local x1 = xmargin
local y1 = ymargin*num
local x2 = x1+159
local y2 = y1+35
--When the mouse is OVER this section...
if io.getMouseX() > x1 and io.getMouseX() < x2 and io.getMouseY() > y1 and io.getMouseY() < y2 then
--Draw the inside box
gr.setColor(0, 255, 0)
gr.drawRectangle(x1+5, y1+5, x2-5, y2-5, false, false)
--Draw the little target lines now
local x = x1+(x2-x1)/2
local y = y1-20
--Top target line
gr.drawLine(x, y, x, y+15)
--Bottom target line
y = y2+10
gr.drawLine(x, y, x, y+15)
--Left target line
x = x1-20
y = y1+17
gr.drawLine(x, y, x+15, y)
--Right target line
x = x2+5
gr.drawLine(x, y, x+15, y)
--Handle the button click
if io.isMouseButtonDown(MOUSE_LEFT_BUTTON) then
gr.drawRectangle(x1, y1, x2, y2, false, false)
if event == "GS_EVENT_NEW_CAMPAIGN" then
mn.unloadMission()
g_missionLoaded = nil
g_splashScreen = nil
end
ba.postGameEvent(ba.GameEvents[event])
end
end
--Draw the outline
gr.setColor(255, 255, 255)
gr.drawRectangle(x1, y1, x2, y2, false, false)
--Draw the name
gr.drawString(name, x1 + ( (x2-x1) - gr.getStringWidth(name) ) / 2, y1+15)
end
]
$Application: Freespace 2
$State: GS_STATE_MAIN_MENU
$On State Start: []
+Override: true
$On State End: [
if g_missionLoaded then
mn.unloadMission()
g_missionLoaded = nil
g_splashScreen = nil
end
]
+Override: true
$On Frame: [
if not g_splashScreen then
--Don't need cursor
io.setCursorHidden(true)
--Draw splash image
local tex = gr.loadTexture("2_PreLoad.dds")
if tex:isValid() then
gr.drawImage(tex, 0, 0, gr.getScreenWidth(), gr.getScreenHeight())
end
--Draw "Loading..."
gr.setColor(255, 255, 255)
gr.CurrentFont = gr.Fonts['font02']
local loadString = "Loading..."
local x = (gr.getScreenWidth()-gr.getStringWidth(loadString))/2
local y = (gr.getScreenHeight()-gr.CurrentFont.Height)/2
gr.drawString(loadString, x, y)
--Done with splash
gr.CurrentFont = gr.Fonts['font01']
g_splashScreen = true
elseif not g_missionLoaded then
mn.loadMission("sm2-06.fs2")
io.setCursorHidden(false)
g_missionLoaded = true
end
if g_missionLoaded then
mn.simulateFrame()
mn.renderFrame()
section("Ready Room", "GS_EVENT_NEW_CAMPAIGN", 1)
section("Campaign Room", "GS_EVENT_CAMPAIGN_ROOM", 2)
section("Tech Room", "GS_EVENT_TECH_MENU", 3)
section("Barracks", "GS_EVENT_BARRACKS_MENU", 4)
section("Options", "GS_EVENT_OPTIONS_MENU", 5)
section("Exit", "GS_EVENT_QUIT_GAME", 6)
end
]
+Override: true
#End
This script seems to be much more reliable. It has two major changes:
One, it unloads the mission whenever you leave the main hall - this happens when you go to the barracks, campaign room, and techroom. Those rooms tend to access the campaign file (At least, the techroom and campaign room do, I didn't check the barracks). This reinitializes the SEXPs, which doesn't do good things for the main menu mission, which is already using them. By unloading the mission and then reloading it when you return to the mainhall, it gets around the SEXP issue.
The options screen works simply as an overlay over the mainhall and essentially pauses the mission underneath, so it doesn't have to reload the mission.
Two, the ready room requires something special. Since making the call to postGameEvent actually loads up the current mission name before it changes the state (switches out of the main hall), unloading the mission also clears that data. So instead I added a special condition to the section() function to handle that case, and unload the main menu mission before the call to postGameEvent. This also seems to fix the problem of exiting out of the game instead of to the main menu.
Result:
With the changes in the new script, the mission mainhall is at the point where I'd consider it a viable option for a release. The downside is that you need to watch what you put in the main menu mission, since it'll have to reload it often. Definitely include ibx files for any models used in it, and if you can remove weapons from ships that you don't care about, disable the support ship, and things like that, that would help too. It'll keep less media from being loaded. FS2 does seem to store things in memory properly with main hall missions, so once the main hall is loaded the first time, it'll take less time the next few times you load it.
Alternatives:
Moving the place that mission names are loaded would make the above script simpler but would require reloading the mission.
Rewriting the SEXP system to be more object-oriented and outside functions to take that into account, so you could have more than one SEXP system operational at the same time, would be one option. Another option would be to save the state of the SEXP system when loading a campaign, and then restore it after you're finished with the campaign SEXPs. Either way, you'd need to be pretty careful and I'm reluctant to do either one for 3.6.10 unless it's proven impossible to load main menu missions in a reasonable amount of time.