Hi all!
I'm usually pretty dormant in the community and this is my first attempt at a major contribution, so bear with me.
For the last few weeks I've been intensely engaged in a project to try and dramatically improve the co-op experience in FSO-based games. This has mainly been oriented around two goals:
* Enable Command Briefings for multiplayer
* Enable Cutscenes for multiplayer
Yeah, there are other issues such as the quirky netcode and inconsistent network replication for newer code features, but that's a little outside my current scope of knowledge to address (yet
) But something I do value greatly is the ability to have the same experience in co-op multiplayer that you can in singleplayer - that is, all cutscenes, and all the command briefings, propogated correctly to all multiplayer clients, all seamlessly integrated, with the same animations, text overlays, etc.
Having spent a couple of weeks giving myself a literal crash-course in the game's source code and scripting system (seriously, I still barely know LUA or C++ at all), I think I've managed to pull together a creative solution for this. Behold - this is a snippet from my primary goal of porting the entire Freespace 1 campaign (with working cutscenes and command briefings) to co-op, which will be coming out soon:
This isn't necessarily the
most elegant solution, because the absolute greatest approach would be to just integrate all this into the native codebase. However, since that would require an extreme amount of work, I've come up with this workaround:
* Command Briefings are individual missions built into the co-op campaign structure. When started, multi-eval and show-subtitle SEXPs are used in combination with a bit of crafty scripting to present the CommandBriefing overlay, as well as play the associated animations (thanks for the
assistance guys!). The briefings are a bit crude and hotkey (not mouse)-driven, but work consistently for both host and client players in presenting the briefing data. At the end, the command briefing "system" cleans up and players can move on to the next actual mission in the campaign.
* Cutscenes work by a script that hooks into GS_STATE_BRIEFING (i.e. right after a mission loads). It'll scroll through a list and see if the mission we're on has a corresponding cutscene, and if so, play it using a new scripting function I exposed (tentatively labelled playCutscene() ), which just gives me an easy ability to call the internal playmovie() function whenever I want. This script processing is local and so works seamlessly for both host and client at playing cutscenes.
What I need to finish this:The problem is that to get all of this working, I've had to make a few discreet code changes - some a bit more questionable than others. I've submitted Mantis tickets regarding these changes already so they can be reviewed properly, as I'm not sure if what I've done is really for the best. I know the code maintainers are busy and all requests will be looked at in due time, but was hoping to put some additional context and attention around these particular requests to see if there was a chance of getting them wrapped up a bit sooner for my co-op mod.
I've already had some help in getting multi-eval added to trunk (
http://scp.indiegames.us/mantis/view.php?id=3079) and fixing a nasty memory problem (
http://scp.indiegames.us/mantis/view.php?id=3084), and have submitted additional Mantis tickets for what's left:
*
show-subtitle-text SEXP causes MP clients (but not host) to crash if message over 32 characters is sent (Mantis 3077)
Sort of self-explanatory. My current implementation for the FS1 Co-Op project relies heavily on show-subtitle-text for Command Briefings, which is supposed to support up to 255 characters per-messages. When playing multiplayer however, clients will crash out if they process messages over 32 characters. I have a minor code change that fixes this, but Karajorma's feedback is this may cause other problems. An ultimate solution would be welcome, as the only alternative is that I port everything over to use something else instead (maybe some kind of crazy gr.drawString() implementation) which would be a fair amount of extra work at this point.
*
mn.getMissionFilenname() doesn't return a value if in GS_STATE_BRIEFING (Mantis 3093)
For my multiplayer-friendly cutscene script to work, I hook into the GS_STATE_BRIEFING state, iterate through a list of lines, and compare the results to the currently-loaded mission file. If we get a match (i.e. we're on a mission where a cutscene is supposed to play), the cutscene triggers. The problem is that mn.getMissionFilename() doesn't seem to work when you're entering the briefing stage because of a check to confirm if your game mode is "GM_IN_MISSION" or not. My workaround was to simply comment out this check and my script works perfectly, but I'm guessing this if-check exists for a good reason. Is there a better solution? I tried appending an OR check for GS_STATE_BRIEFING using other examples in lua.cpp as a guide, but this still returned nil values.
*
Request for new scripting function: ts.playCutscene() (.patch included) (Mantis 3094)
A second necessary component for my multiplayer-friendly cutscene script to work. This adds the ts.playCutscene() scripting function (experimental), as currently multiplayer clients won't process the standard movie play requests when the host starts a campaign mission that's supposed to have a cutscene. A secondary problem to this I've noticed is that while the cutscene plays, network processing is suspended and you might return to find you've been booted out of the game with a "timeout" error. I'm looking at addressing this seperately, but for now the workaround is just to use the -timeout argument on your game client and set it to a value higher than the cutscene play time.
And that's about it. One goal with this was to minimize any source code changes as much as possible, but in these cases I couldn't see any other way to accomplish my objectives (maybe I'm just not smart enough, heh). Input into these would be much appreciated.
Otherwise, the FS1 portion of this project is nearing completion - I just have to wrap up the last leg of the campaign and do some more internal testing. Even if all if these changes had to be compiled into a separate test branch of the code, I'd love if I could link to that rather than distributing my own NOTAVIRUS.EXE with the mod. I'll make a big announcement on the FSPort board when this is all ready to roll, and will then be moving on to the FS2 campaign.
Thanks! And apologies again if I'm going about this the wrong way - I'm excited by the opportunities this will bring the community to make FSO's co-op play a bit more popular and hope this turns out to be really useful.
(Here's the part where you tell me all of this has already been implemented in some manner and all my work is for naught...)