diff --git a/code/cutscene/cutscenes.cpp b/code/cutscene/cutscenes.cpp index 087f6d86e4b..29ca15b1800 100644 --- a/code/cutscene/cutscenes.cpp +++ b/code/cutscene/cutscenes.cpp @@ -354,32 +354,25 @@ static const char* Text_lines[MAX_TEXT_LINES]; void cutscenes_screen_play() { - char name[MAX_FILENAME_LEN]; // *full_name - int which_cutscene; - - Assert((Selected_line >= 0) && (Selected_line < (int) Cutscene_list.size())); - which_cutscene = Cutscene_list[Selected_line]; - - strcpy_s(name, Cutscenes[which_cutscene].filename); -// full_name = cf_add_ext(name, NOX(".mve")); + Assertion(SCP_vector_inbounds(Cutscene_list, Selected_line), "Selected line %d is out of range!", Selected_line); + int which_cutscene = Cutscene_list[Selected_line]; main_hall_stop_music(true); main_hall_stop_ambient(); - auto rval = movie::play(name); + auto rval = movie::play(Cutscenes[which_cutscene].filename, true); main_hall_start_music(); if (!rval) { - char str[256]; + SCP_string str; if (Cmdline_nomovies) - strcpy_s(str, XSTR("Movies are currently disabled.", 1574)); + str = XSTR("Movies are currently disabled.", 1574); else sprintf(str, XSTR("Unable to play movie %s.", 204), Cutscenes[which_cutscene].name); - popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, str); + popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, str.c_str()); } - } void cutscenes_screen_scroll_line_up() diff --git a/code/cutscene/movie.cpp b/code/cutscene/movie.cpp index 12bcc41e251..f8d7633db8c 100644 --- a/code/cutscene/movie.cpp +++ b/code/cutscene/movie.cpp @@ -30,6 +30,7 @@ #include "io/key.h" #include "mod_table/mod_table.h" #include "network/multi.h" +#include "scripting/global_hooks.h" extern int Game_mode; extern int Is_standalone; @@ -272,12 +273,22 @@ void movie_display_loop(Player* player, PlaybackState* state) { namespace movie { // Play one movie -bool play(const char* name) { +bool play(const char* filename, bool via_tech_room = false) +{ + if (scripting::hooks::OnMovieAboutToPlay->isActive()) + { + auto paramList = scripting::hook_param_list(scripting::hook_param("Filename", 's', filename), scripting::hook_param("ViaTechRoom", 'b', via_tech_room)); + bool skip = scripting::hooks::OnMovieAboutToPlay->isOverride(paramList); + scripting::hooks::OnMovieAboutToPlay->run(paramList); + if (skip) + return false; + } + // mark the movie as viewable to the player when in a campaign // do this before anything else so that we're sure the movie is available // to the player even if it's not going to play right now if (Game_mode & GM_CAMPAIGN_MODE) { - cutscene_mark_viewable(name); + cutscene_mark_viewable(filename); } if (Cmdline_nomovies || Is_standalone) { @@ -306,7 +317,7 @@ bool play(const char* name) { // clear third buffer (may not be one, but that's ok) gr_clear(); - auto player = cutscene::Player::newPlayer(name); + auto player = cutscene::Player::newPlayer(filename); if (player) { PlaybackState state; initialize_player_state(player.get(), &state); @@ -316,7 +327,7 @@ bool play(const char* name) { player->stopPlayback(); } else { // uh-oh, movie is invalid... Abory, Retry, Fail? - mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name)); + mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", filename)); } Movie_active = false; @@ -327,9 +338,9 @@ bool play(const char* name) { return true; } -void play_two(const char* name1, const char* name2) { - if (play(name1)) { - play(name2); +void play_two(const char* filename1, const char* filename2) { + if (play(filename1)) { + play(filename2); } } } diff --git a/code/cutscene/movie.h b/code/cutscene/movie.h index 666feecc2b6..e06f03bafc4 100644 --- a/code/cutscene/movie.h +++ b/code/cutscene/movie.h @@ -14,9 +14,9 @@ namespace movie { -bool play(const char* name); +bool play(const char* filename, bool via_tech_room = false); -void play_two(const char* name1, const char* name2); +void play_two(const char* filename1, const char* filename2); } diff --git a/code/mission/missioncampaign.cpp b/code/mission/missioncampaign.cpp index f53fb2887eb..1e80309918d 100644 --- a/code/mission/missioncampaign.cpp +++ b/code/mission/missioncampaign.cpp @@ -1468,7 +1468,6 @@ void mission_campaign_maybe_play_movie(int type) return; movie::play(filename); //Play the movie! - cutscene_mark_viewable( filename ); } /** diff --git a/code/missionui/missionscreencommon.cpp b/code/missionui/missionscreencommon.cpp index 055cbadc6c5..162fb1c1ee0 100644 --- a/code/missionui/missionscreencommon.cpp +++ b/code/missionui/missionscreencommon.cpp @@ -407,7 +407,6 @@ void common_maybe_play_cutscene(int movie_type, bool restart_music, int music) common_music_close(); music_off = true; movie::play(The_mission.cutscenes[i].filename); //Play the movie! - cutscene_mark_viewable( The_mission.cutscenes[i].filename ); } } } diff --git a/code/scripting/global_hooks.cpp b/code/scripting/global_hooks.cpp index 070a03db827..bc79a3b0fe9 100644 --- a/code/scripting/global_hooks.cpp +++ b/code/scripting/global_hooks.cpp @@ -16,13 +16,20 @@ const std::shared_ptr> OnSplashEnd = Hook<>::Factory("On Splash End", "Executed just after the splash screen fades out.", {}); -const std::shared_ptr> OnIntroAboutToPlay = Hook<>::Factory("On Intro About To Play", +const std::shared_ptr> OnIntroAboutToPlay = OverridableHook<>::Factory("On Intro About To Play", "Executed just before the intro movie is played.", {}); +const std::shared_ptr> OnMovieAboutToPlay = OverridableHook<>::Factory("On Movie About To Play", + "Executed just before any cutscene movie is played.", + { + {"Filename", "string", "The filename of the movie that is about to play."}, + {"ViaTechRoom", "boolean", "Whether the movie player was invoked through the tech room."}, + }); + const std::shared_ptr> OnStateStart = OverridableHook<>::Factory("On State Start", "Executed whenever a new state is entered.", - { + { {"OldState", "gamestate", "The gamestate that was executing."}, {"NewState", "gamestate", "The gamestate that will be executing."} }); diff --git a/code/scripting/global_hooks.h b/code/scripting/global_hooks.h index 7c623fbd302..1467a91371d 100644 --- a/code/scripting/global_hooks.h +++ b/code/scripting/global_hooks.h @@ -7,7 +7,8 @@ namespace hooks { extern const std::shared_ptr> OnGameInit; extern const std::shared_ptr> OnSplashEnd; -extern const std::shared_ptr> OnIntroAboutToPlay; +extern const std::shared_ptr> OnIntroAboutToPlay; +extern const std::shared_ptr> OnMovieAboutToPlay; //The On State Start hook previously used to pass OldState to the conditions, but no semantically sensible condition read the value, so we pretend it has no local condition extern const std::shared_ptr> OnStateStart; diff --git a/freespace2/freespace.cpp b/freespace2/freespace.cpp index 8c07534b731..be6fc49b758 100644 --- a/freespace2/freespace.cpp +++ b/freespace2/freespace.cpp @@ -6850,11 +6850,13 @@ int game_main(int argc, char *argv[]) output_sexps("sexps.html"); } + bool skip_intro = false; if (scripting::hooks::OnIntroAboutToPlay->isActive()) { + skip_intro = scripting::hooks::OnIntroAboutToPlay->isOverride(); scripting::hooks::OnIntroAboutToPlay->run(); } - if (!Is_standalone) { + if (!Is_standalone && !skip_intro) { movie::play("intro.mve"); }