@@ -175,6 +175,27 @@ p_object *Player_start_pobject;
175175// something before that ship has even been loaded yet)
176176SCP_vector<SCP_string> Parse_names;
177177
178+ SCP_vector<SCP_string> Mission_parse_warnings;
179+
180+ // Routes a parse-time auto-correction notice to the right surface for the app:
181+ // outside QtFRED, the existing Warning(LOCATION, ...) popup; inside QtFRED, the
182+ // Mission_parse_warnings queue so the ErrorChecker can present it without a popup.
183+ static void parse_warning_or_record (SCP_FORMAT_STRING const char * fmt, ...) SCP_FORMAT_STRING_ARGS(1 , 2 );
184+ static void parse_warning_or_record (const char * fmt, ...)
185+ {
186+ SCP_string msg;
187+ va_list args;
188+ va_start (args, fmt);
189+ vsprintf (msg, fmt, args);
190+ va_end (args);
191+
192+ if (Qtfred_running) {
193+ Mission_parse_warnings.push_back (std::move (msg));
194+ } else {
195+ Warning (LOCATION , " %s" , msg.c_str ());
196+ }
197+ }
198+
178199SCP_vector<texture_replace> Fred_texture_replacements;
179200
180201SCP_unordered_set<int > Fred_migrated_immobile_ships;
@@ -2426,10 +2447,10 @@ int parse_create_object_sub(p_object *p_objp, bool standalone_ship)
24262447 // will accept were apparently written out incorrectly with Fred. This Int3() should
24272448 // trap these instances.
24282449#ifndef NDEBUG
2429- if (Fred_running)
2450+ if (Fred_running && !Qtfred_running )
24302451 {
24312452 std::set<size_t > default_orders, remaining_orders;
2432-
2453+
24332454 default_orders = ship_get_default_orders_accepted (&Ship_info[shipp->ship_info_index ]);
24342455 std::set_difference (p_objp->orders_accepted .begin (), p_objp->orders_accepted .end (), default_orders.begin (), default_orders.end (),
24352456 std::inserter (remaining_orders, remaining_orders.begin ()));
@@ -2963,7 +2984,7 @@ void resolve_parse_flags(object *objp, flagset<Mission::Parse_Object_Flags> &par
29632984
29642985 if ((parse_flags[Mission::Parse_Object_Flags::OF_No_shields]) && (parse_flags[Mission::Parse_Object_Flags::OF_Force_shields_on]))
29652986 {
2966- Warning ( LOCATION , " The parser found a ship with both the \" force-shields-on\" and \" no-shields\" flags; this is inconsistent! " );
2987+ parse_warning_or_record ( " Ship %s has both the \" force-shields-on\" and \" no-shields\" flags; this is inconsistent. " , shipp-> ship_name );
29672988 }
29682989 if (parse_flags[Mission::Parse_Object_Flags::OF_No_shields])
29692990 objp->flags .set (Object::Object_Flags::No_shields);
@@ -3458,7 +3479,7 @@ int parse_object(mission *pm, int /*flag*/, p_object *p_objp)
34583479 || (p_objp->arrival_location == ArrivalLocation::ABOVE_SHIP ) || (p_objp->arrival_location == ArrivalLocation::BELOW_SHIP )
34593480 || (p_objp->arrival_location == ArrivalLocation::TO_LEFT_OF_SHIP ) || (p_objp->arrival_location == ArrivalLocation::TO_RIGHT_OF_SHIP ) ))
34603481 {
3461- Warning ( LOCATION , " Arrival distance for ship %s cannot be %d. Setting to 1.\n " , p_objp->name , p_objp->arrival_distance );
3482+ parse_warning_or_record ( " Arrival distance for ship %s cannot be %d — corrected to 1." , p_objp->name , p_objp->arrival_distance );
34623483 p_objp->arrival_distance = 1 ;
34633484 }
34643485 }
@@ -3483,7 +3504,7 @@ int parse_object(mission *pm, int /*flag*/, p_object *p_objp)
34833504 stuff_int (&delay);
34843505 if (delay < 0 )
34853506 {
3486- Warning ( LOCATION , " Cannot have arrival delay < 0 on ship %s" , p_objp->name );
3507+ parse_warning_or_record ( " Arrival delay on ship %s cannot be negative — corrected to 0. " , p_objp->name );
34873508 delay = 0 ;
34883509 }
34893510
@@ -3520,7 +3541,7 @@ int parse_object(mission *pm, int /*flag*/, p_object *p_objp)
35203541 stuff_int (&delay);
35213542 if (delay < 0 )
35223543 {
3523- Warning ( LOCATION , " Cannot have departure delay < 0 ( ship %s) " , p_objp->name );
3544+ parse_warning_or_record ( " Departure delay on ship %s cannot be negative — corrected to 0. " , p_objp->name );
35243545 delay = 0 ;
35253546 }
35263547
@@ -3752,7 +3773,7 @@ int parse_object(mission *pm, int /*flag*/, p_object *p_objp)
37523773 stuff_int (&p_objp->destroy_before_mission_time );
37533774 if (p_objp->destroy_before_mission_time < 0 )
37543775 {
3755- Warning ( LOCATION , " Cannot set a negative 'destroy before mission' value ( ship %s) " , p_objp->name );
3776+ parse_warning_or_record ( " 'Destroy before mission' value on ship %s cannot be negative — corrected to 0. " , p_objp->name );
37563777 p_objp->destroy_before_mission_time = 0 ;
37573778 }
37583779
@@ -3847,7 +3868,7 @@ int parse_object(mission *pm, int /*flag*/, p_object *p_objp)
38473868 if (optional_string (" +Persona Index:" )) {
38483869 stuff_int (&p_objp->persona_index );
38493870 if (p_objp->persona_index < -1 || p_objp->persona_index >= (int )Personas.size ()) {
3850- Warning ( LOCATION , " Persona index %d for %s is out of range! Setting to -1." , p_objp->persona_index , p_objp->name );
3871+ parse_warning_or_record ( " Persona index %d for ship %s is out of range — corrected to -1." , p_objp->persona_index , p_objp->name );
38513872 p_objp->persona_index = -1 ;
38523873 }
38533874 }
@@ -4915,7 +4936,7 @@ void parse_wing(mission *pm)
49154936 || (wingp->arrival_location == ArrivalLocation::ABOVE_SHIP ) || (wingp->arrival_location == ArrivalLocation::BELOW_SHIP )
49164937 || (wingp->arrival_location == ArrivalLocation::TO_LEFT_OF_SHIP ) || (wingp->arrival_location == ArrivalLocation::TO_RIGHT_OF_SHIP ) ))
49174938 {
4918- Warning ( LOCATION , " Arrival distance for wing %s cannot be %d. Setting to 1.\n " , wingp->name , wingp->arrival_distance );
4939+ parse_warning_or_record ( " Arrival distance for wing %s cannot be %d — corrected to 1." , wingp->name , wingp->arrival_distance );
49194940 wingp->arrival_distance = 1 ;
49204941 }
49214942 }
@@ -4940,7 +4961,7 @@ void parse_wing(mission *pm)
49404961 stuff_int (&delay);
49414962 if (delay < 0 )
49424963 {
4943- Warning ( LOCATION , " Cannot have arrival delay < 0 on wing %s" , wingp->name );
4964+ parse_warning_or_record ( " Arrival delay on wing %s cannot be negative — corrected to 0. " , wingp->name );
49444965 delay = 0 ;
49454966 }
49464967
@@ -4977,7 +4998,7 @@ void parse_wing(mission *pm)
49774998 stuff_int (&delay);
49784999 if (delay < 0 )
49795000 {
4980- Warning ( LOCATION , " Cannot have departure delay < 0 on wing %s" , wingp->name );
5001+ parse_warning_or_record ( " Departure delay on wing %s cannot be negative — corrected to 0. " , wingp->name );
49815002 delay = 0 ;
49825003 }
49835004
@@ -5152,7 +5173,7 @@ void parse_wing(mission *pm)
51525173
51535174 // Goober5000 - if this is a player start object, there shouldn't be a wing arrival delay (Mantis #2678)
51545175 if ((p_objp->flags [Mission::Parse_Object_Flags::OF_Player_start]) && (wingp->arrival_delay != 0 )) {
5155- Warning ( LOCATION , " Wing %s specifies an arrival delay of %ds, but it also contains a player. The arrival delay will be reset to 0." , wingp->name , abs (wingp->arrival_delay ));
5176+ parse_warning_or_record ( " Wing %s specifies an arrival delay of %ds, but it also contains a player — corrected to 0." , wingp->name , abs (wingp->arrival_delay ));
51565177 if (!Fred_running && wingp->arrival_delay > 0 ) {
51575178 // timestamp has been set, so set it again
51585179 wingp->arrival_delay = timestamp (0 );
@@ -5423,7 +5444,9 @@ void post_process_ships_wings()
54235444 // error checking for custom wings
54245445 if (strcmp (Starting_wing_names[0 ], TVT_wing_names[0 ]) != 0 )
54255446 {
5426- Error (LOCATION , " The first starting wing and the first team-versus-team wing must have the same wing name.\n " );
5447+ // In QtFRED this is surfaced via ErrorChecker::checkPlayerWings so the editor can load the mission.
5448+ if (!Qtfred_running)
5449+ Error (LOCATION , " The first starting wing and the first team-versus-team wing must have the same wing name.\n " );
54275450 }
54285451
54295452 // set up wing indexes
@@ -5610,7 +5633,7 @@ void post_process_ships_wings()
56105633 for (int i = 1 ; i < MAX_STARTING_WINGS ; i++) {
56115634 // If there was a wing for this squadron entry, check the last one. If it's empty, we found a mistake, so move the wing names over.
56125635 if (Squadron_wing_names_found[i] && !Squadron_wing_names_found[i - 1 ]) {
5613- Warning ( LOCATION , " Squadron wings are not in the correct order and may cause wings to disappear in multi.\n\n Either wing %s should exist or the %s entry needs to come before it in the list. \n\n Please go back and fix the mission ." , Squadron_wing_names[i - 1 ], Squadron_wing_names[i]);
5636+ parse_warning_or_record ( " Squadron wings are not in the correct order and may cause wings to disappear in multi. Either wing %s should exist or the %s entry needs to come before it in the list — wing names have been swapped ." , Squadron_wing_names[i - 1 ], Squadron_wing_names[i]);
56145637 char temp_chars[NAME_LENGTH ];
56155638 strcpy_s (temp_chars, Squadron_wing_names[i - 1 ]);
56165639 strcpy_s (Squadron_wing_names[i - 1 ], Squadron_wing_names[i]);
@@ -5648,7 +5671,7 @@ void parse_event(mission *pm)
56485671 // sanity check on the repeat count variable
56495672 // _argv[-1] - negative repeat count is now legal; means repeat indefinitely.
56505673 if ( event->repeat_count == 0 ){
5651- Warning ( LOCATION , " Repeat count for mission event %s is 0. \n Must be >= 1 or negative! Setting to 1." , event->name .c_str () );
5674+ parse_warning_or_record ( " Repeat count for mission event %s is 0 — must be >= 1 or negative; corrected to 1." , event->name .c_str ());
56525675 event->repeat_count = 1 ;
56535676 }
56545677 }
@@ -5665,7 +5688,7 @@ void parse_event(mission *pm)
56655688 // sanity check on the trigger count variable
56665689 // negative trigger count is also legal
56675690 if ( event->trigger_count == 0 ){
5668- Warning ( LOCATION , " Trigger count for mission event %s is 0. \n Must be >= 1 or negative! Setting to 1." , event->name .c_str () );
5691+ parse_warning_or_record ( " Trigger count for mission event %s is 0 — must be >= 1 or negative; corrected to 1." , event->name .c_str ());
56695692 event->trigger_count = 1 ;
56705693 }
56715694 }
@@ -6021,7 +6044,7 @@ void parse_reinforcement(mission *pm)
60216044 stuff_int (&delay);
60226045 if (delay < 0 )
60236046 {
6024- Warning ( LOCATION , " Cannot have arrival delay < 0 on reinforcement %s" , ptr->name );
6047+ parse_warning_or_record ( " Arrival delay on reinforcement %s cannot be negative — corrected to 0. " , ptr->name );
60256048 delay = 0 ;
60266049 }
60276050
@@ -6041,14 +6064,14 @@ void parse_reinforcement(mission *pm)
60416064
60426065 if (rforce_obj == NULL ) {
60436066 if ((instance = wing_name_lookup (ptr->name , 1 )) == -1 ) {
6044- Warning ( LOCATION , " Reinforcement %s not found as ship or wing" , ptr->name );
6067+ parse_warning_or_record ( " Reinforcement %s not found as ship or wing — declaration ignored. " , ptr->name );
60456068 return ;
60466069 }
60476070 } else {
60486071 // Individual ships in wings can't be reinforcements - FUBAR
60496072 if (rforce_obj->wingnum >= 0 )
60506073 {
6051- Warning ( LOCATION , " Reinforcement %s is part of a wing - Ignoring reinforcement declaration" , ptr->name );
6074+ parse_warning_or_record ( " Reinforcement %s is part of a wing — reinforcement declaration ignored. " , ptr->name );
60526075 return ;
60536076 }
60546077 else
@@ -6698,6 +6721,9 @@ bool parse_mission(mission *pm, int flags)
66986721 int saved_warning_count = Global_warning_count;
66996722 int saved_error_count = Global_error_count;
67006723
6724+ // Reset the parse-time warning queue so each load starts fresh (only consumed by QtFRED).
6725+ Mission_parse_warnings.clear ();
6726+
67016727 // reset parse error stuff
67026728 Num_unknown_ship_classes = 0 ;
67036729 Num_unknown_prop_classes = 0 ;
@@ -6798,7 +6824,9 @@ bool parse_mission(mission *pm, int flags)
67986824 if (!post_process_mission (pm))
67996825 return false ;
68006826
6801- if ((saved_warning_count - Global_warning_count) > 10 || (saved_error_count - Global_error_count) > 0 ) {
6827+ // QtFRED surfaces parse issues through its own error checker, so skip this summary popup there; Fred2 and the game still show it.
6828+ if (!Qtfred_running &&
6829+ ((saved_warning_count - Global_warning_count) > 10 || (saved_error_count - Global_error_count) > 0 )) {
68026830 char text[512 ];
68036831 sprintf (text, " Warning!\n\n The current mission has generated %d warnings and/or errors during load. These are usually caused by corrupted ship models or syntax errors in the mission file. While FreeSpace Open will attempt to compensate for these issues, it cannot guarantee a trouble-free gameplay experience. Source Code Project staff cannot provide assistance or support for these problems, as they are caused by the mission's data files, not FreeSpace Open's source code." , (saved_warning_count - Global_warning_count) + (saved_error_count - Global_error_count));
68046832 popup (PF_TITLE_BIG | PF_TITLE_RED | PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING , 1 , POPUP_OK , text);
@@ -6936,7 +6964,9 @@ bool post_process_mission(mission *pm)
69366964 error_msg += " \n\n (Bad node appears to be: " ;
69376965 error_msg += bad_node_str;
69386966 error_msg += " )\n " ;
6939- Warning (LOCATION , " %s" , error_msg.c_str ());
6967+ // QtFRED surfaces SEXP errors through ErrorChecker's fred_check_sexp; skip the popup there.
6968+ if (!Qtfred_running)
6969+ Warning (LOCATION , " %s" , error_msg.c_str ());
69406970
69416971 // syntax errors are recoverable in Fred but not FS
69426972 if (!Fred_running && !sexp_recoverable_error (result)) {
@@ -7734,15 +7764,17 @@ void mission_parse_set_up_initial_docks()
77347764 // display an error if necessary
77357765 if (dfi.maintained_variables .int_value == 0 )
77367766 {
7737- Warning (LOCATION , " In the docking group containing %s, every ship has an arrival cue set to false. The group will not appear in-mission!\n " , pobjp->name );
7767+ if (!Qtfred_running)
7768+ Warning (LOCATION , " In the docking group containing %s, every ship has an arrival cue set to false. The group will not appear in-mission!\n " , pobjp->name );
77387769
77397770 // for FRED, we must arbitrarily choose a dock leader, otherwise the entire docked group will not be loaded
77407771 if (Fred_running)
77417772 dock_evaluate_all_docked_objects (pobjp, &dfi, parse_object_choose_arbitrary_dock_leader_helper);
77427773 }
77437774 else if (dfi.maintained_variables .int_value > 1 )
77447775 {
7745- Warning (LOCATION , " In the docking group containing %s, there is more than one ship with a non-false arrival cue! There can only be one such ship. Setting all arrival cues except %s to false...\n " , dfi.maintained_variables .objp_value ->name , dfi.maintained_variables .objp_value ->name );
7776+ if (!Qtfred_running)
7777+ Warning (LOCATION , " In the docking group containing %s, there is more than one ship with a non-false arrival cue! There can only be one such ship. Setting all arrival cues except %s to false...\n " , dfi.maintained_variables .objp_value ->name , dfi.maintained_variables .objp_value ->name );
77467778 }
77477779
77487780 // clear dfi stuff
0 commit comments