Compare commits

...
Author SHA1 Message Date
Tyler Blount b662a5a716 Increase Weapon Info Limit 2020-05-09 16:56:20 -06:00
Fabian Woltermann 94bd8da5db Merge pull request #2373 from Goober5000/parse_tweaks
some code tweaks from an old branch
2020-05-09 20:21:01 +02:00
Fabian Woltermann 03926b8dde Merge pull request #2379 from The-E/fix/naked_int3_in_missionmessage
Remove naked int3() call in missionmessage
2020-05-09 18:44:18 +02:00
Fabian Woltermann 764bbac99f The original Volition code called Int3() here; since there is a way out that does not require us to crash, we should just not crash. 2020-05-09 10:43:13 +02:00
Goober5000 d52bddf0dc Merge pull request #2347 from EatThePath/disable-doublefire-take-2
Disable doublefire take 2
2020-05-08 02:01:40 -04:00
Goober5000 0e9a72a37b make clang happy 2020-05-07 21:57:18 -04:00
David Gibson b88ccfb924 added an explanatory comment. Also reunited some related code I'd inadvertantly pushed apart, per review. 2020-05-07 15:09:19 -05:00
Fabian Woltermann 4005a60b32 Merge pull request #2375 from The-E/fix/damage_lightning_in_lab
Make the lab's "show damage lightning" flag work again.
2020-05-07 21:31:48 +02:00
Fabian Woltermann 2e6306d85f Merge pull request #2374 from The-E/fix/texture_replacement_in_lab
Apply tabled texture replacements when loading ships in the F3 lab
2020-05-07 20:36:16 +02:00
Fabian Woltermann e1f231fcf0 Use the tabled max hull strength instead of a constant 2020-05-07 19:01:36 +02:00
Fabian Woltermann 86e898c9ea Use modern loops 2020-05-07 16:04:06 +02:00
Fabian Woltermann df1491fd9e Make the lab's "show damage lightning" flag work again.
Note that it may take a few frames for lightning to disappear when unchecking that checkbox.
2020-05-07 15:18:56 +02:00
Fabian Woltermann 0b8f203371 Apply tabled texture replacements when loading ships in the F3 lab 2020-05-07 14:48:14 +02:00
wookieejedi 1d152fcc73 Merge pull request #2371 from wookieejedi/on-depature-started-hook
Add `On Departure Started` Hook
2020-05-06 22:48:42 -04:00
Goober5000 c9fb046024 update header 2020-05-06 14:38:40 -04:00
Goober5000 c4b8020ebc some code tweaks from an old branch
Minor edits from an obsolete branch that are still useful in cleaning up the code.
2020-05-06 14:25:08 -04:00
wookieejedi a2c7a344da Add On Departure Started Hook
This PR adds a scripting hook which triggers when a ship begins it's departure process. It has one variable that is the ship. I have tested and it works as expected. This new hook is very useful for triggering events whenever a ship needs an alteration to it's departure methods. For example, in Fate of the Galaxy we require ships to warp out along a certain vector. This hook allows us to see when the ship is begining that depature and then break the ship's warp, order the ship to instead follow a waypoint path, and then jump out.
2020-05-06 09:25:10 -04:00
Goober5000 f8e5c9f7a3 Merge pull request #2343 from Goober5000/fix_mantis_2942
implement XSTR check as described in Mantis 2942
2020-05-05 22:28:20 -04:00
wookieejedi bebb69e28f Merge pull request #2369 from wookieejedi/pain-flash-hook
Adds `On Pain Flash` Scripting Hook
2020-05-05 16:59:45 -04:00
Goober5000 aef4c1ba3c address feedback 2020-05-05 14:38:50 -04:00
Goober5000 801a6031e3 Merge pull request #2367 from Goober5000/aiturret_fix
fix some code rot
2020-05-05 14:01:34 -04:00
Goober5000 4c573e2989 Merge pull request #2368 from Goober5000/support_ship_override
add two useful cheat keys
2020-05-05 14:00:59 -04:00
wookieejedi aa4e300153 switch to correct hook type 2020-05-05 13:55:57 -04:00
wookieejedi 3695f0ff93 remove unneeded CHAPAINFLASH 2020-05-05 13:51:36 -04:00
wookieejedi 7dc38f7752 Update to new script format 2020-05-05 13:46:53 -04:00
Goober5000 5ab611a8b1 this reason is only applicable in debug builds 2020-05-05 12:08:22 -04:00
Goober5000 0577b69d69 address CI complaint 2020-05-05 11:48:46 -04:00
wookieejedi 6897024b29 Adds On Pain Flash Scripting Hook
This PR adds a scripting hook which triggers when the pain flash is shown. It has one variable that lists what type of flash was shown, shield with `Pain_Type == 0` and hull with `Pain_Type == 1` .  I have tested and it works as expected.
2020-05-05 10:03:48 -04:00
Fabian Woltermann ffd5fdc764 Merge pull request #2366 from wookieejedi/carry-glowmap-status
Updates glowmap settings for a ship to also apply to ship's cockpit
2020-05-05 10:21:53 +02:00
Goober5000 e985961ed5 add two useful cheat keys
`+Shift+R will enable or disable support ships

`+Shift+U will scan or unscan the targeted ship, or ship subsystem
2020-05-05 01:02:17 -04:00
Goober5000 89a722d41a placeholder for future feature implementation 2020-05-05 00:14:16 -04:00
Goober5000 3ca187127d move comment 2020-05-05 00:01:30 -04:00
Goober5000 35e67d4574 possibly fix some code rot 2020-05-04 23:33:06 -04:00
wookieejedi 8b7253cfc1 Updates glowmap settings for a ship to also apply to ship's cockpit
The sexps that activate and deactive glowmaps are very useful for ships, though previously the glowmap status was not passed to the ship's cockpit. This PR adds the ability for glowmap status to carry to this ship's cockpit (if it has one).
2020-05-04 22:07:49 -04:00
Goober5000 7ec425f341 Merge pull request #2345 from Goober5000/fix_mantis_2791
Fix mantis 2791
2020-05-04 20:27:29 -04:00
Goober5000 e4b2791c4e Merge pull request #2353 from Goober5000/support_ship_cleanup
clean up the support ship code a bit
2020-05-04 16:13:06 -04:00
Fabian Woltermann e5c2b76469 Merge pull request #2363 from The-E/fix/post_process_aa_cmdline
Unify the way post-process antialiasing is switched on
2020-05-04 22:12:39 +02:00
Goober5000 4c5bc1fa6c Merge pull request #2360 from Goober5000/fix_2335
fix issue 2335
2020-05-04 16:12:18 -04:00
Fabian Woltermann 857a622caa Make Travis happy 2020-05-04 21:29:53 +02:00
Fabian Woltermann bdc6145b2c Deprecates the -fxaa and -smaa cmdline parameters in favour of a more generalized -aa; This also ensures that the smaa render targets are always initialized. 2020-05-04 18:30:11 +02:00
wookieejedi 07ce8a9c70 Merge pull request #2362 from wookieejedi/fix-glowmap-explode-flag
Fix Glowmap flag not carrying over to final ship explosion
2020-05-04 07:35:36 -04:00
wookieejedi e42ed47c61 Previously if a ship's glowmaps were deactivated via sexp, then the glowmaps would reaactivie at the ship's final explosinos. This PR fixes that by carrying that flag into the ship explosion FX code.
Previously if a ship's glowmaps were deactivated via sexp, then the glowmaps would reaactivie at the ship's final explosinos. This PR fixes that by carrying that flag into the ship explosion FX code.
2020-05-03 23:36:42 -04:00
Goober5000 ce3b9b62b1 Merge pull request #2336 from Goober5000/hotkey_fixes
add +Hotkey Team: to override IFF designation in hotkey list
2020-05-03 17:29:35 -04:00
Goober5000 794863c5e7 Merge pull request #2348 from Goober5000/mantis_2867
bring save format up to date (Mantis 2867)
2020-05-03 15:42:48 -04:00
Goober5000 38e04b6151 Merge pull request #2354 from Goober5000/cue_voice_tweak
add overlooked generic file
2020-05-02 16:48:56 -04:00
Goober5000 3c76cc6524 add overlooked generic file
It turns out that the extant placeholder wav has an underscore in the filename, so add that to the list.
2020-05-02 13:54:13 -04:00
niffiwan 3c7f73f4d8 Merge pull request #2349 from Goober5000/allow_empty_weapons_on_locked_ships
allow empty weapons on locked ships
2020-05-02 20:01:23 +10:00
Fabian Woltermann 5366073356 Merge pull request #2358 from The-E/fix/aa_shader_unloading
A followup to the recent SMAA fixes
2020-05-01 13:30:56 +02:00
Fabian Woltermann 23fbdf7e64 Clean up the aa shader loading/unloading code to handle cases where we switch between FXAA and SMAA correctly 2020-05-01 10:55:20 +02:00
Goober5000 4cb3b393da clean up the support ship code a bit
Due to code rot, the support ship hull repair code was a bit more tangled than it should have been, so I tidied it up.  I also fixed a bug Sarn noticed where a support ship would think all subsystems were repaired if the hull repair rate was set to 0.
2020-04-29 01:39:18 -04:00
Goober5000 9c44e77da0 allow empty weapons on locked ships
As noticed in Discord, in loop1-2 some of your wingmen have missing weapons, but as the ships are locked it's impossible for the player to modify them.  These ships should not be part of the check.
2020-04-28 23:51:37 -04:00
Goober5000 d9d372121a missed one 2020-04-28 23:24:13 -04:00
Goober5000 6df90a8ec7 newline 2020-04-28 23:12:51 -04:00
Goober5000 289defdeff smol fix 2020-04-28 23:11:33 -04:00
Goober5000 a54ebc3114 bring save format up to date (Mantis 2867)
FSO-specific features should now all be properly marked off with checks for retail format.
2020-04-28 23:02:10 -04:00
David Gibson 4a5ff2860b now check doublefire validity flags before drawing doublefire HUD indicator 2020-04-28 16:06:20 -05:00
David Gibson f8f1b44405 Check doublefire flag validity before firing any missile 2020-04-28 14:50:33 -05:00
David Gibson f13faf4cba added new flags and flag loading for the doublefire disabling options 2020-04-28 13:57:44 -05:00
Goober5000 9dd6bcf81d warn if there is a gap in the path sequence 2020-04-28 00:39:46 -04:00
Goober5000 3356edff2b warn if model paths do not have unique names 2020-04-28 00:16:06 -04:00
Goober5000 07acdde69a fix Mantis 2791
This is a pretty easy fix; sorry it took seven years!

Instead of firing an Int3() when a ship has no arrival paths, just log it and continue.  And change the upstream warnings, which should have been more visible, from WarningEx to Warning.
2020-04-27 23:43:45 -04:00
Goober5000 c89ea8e8dd update test case 2020-04-27 23:22:34 -04:00
Goober5000 d6c1a3dec4 implement XSTR check as described in Mantis 2942
Certain mods provide their own tstrings.tbl, but this runs into trouble when you localize data meant for one mod using a tstrings.tbl meant for another mod.  See the Mantis ticket:
http://scp.indiegames.us/mantis/view.php?id=2942
and also the HLP post:
http://www.hard-light.net/forums/index.php?topic=85041.msg1716600#msg1716600

This PR adds an optional flag that will check the untranslated string against the "default language" translated string.  The two strings should be identical.  If they aren't, the code assumes there is a tstrings.tbl mismatch.

I modified the mission listing code to enable this check when localizing mission info (titles and descriptions), and to avoid adding the mission to the list if there is a mismatch.  Fortunately, I think mission listing is the only place where this bug is likely to happen.
2020-04-27 22:42:13 -04:00
Goober5000 30d41eff8b fix issue 2335
Modify the early-out condition to remain in the function if we still need to render a dumbfire lead indicator.

Fixes #2335.
2020-04-27 20:32:45 -04:00
Goober5000 c8b1f56a09 missed one 2020-04-16 13:37:36 -04:00
Goober5000 8cc9eb2352 change to bool, for great C++ justice 2020-04-16 13:20:39 -04:00
Goober5000 3d08119734 add +Hotkey Team: to override IFF designation in hotkey list
This is in response to Mantis 1424:
http://scp.indiegames.us/mantis/view.php?id=1424

Since retail, the hotkey lists have been determined based on what attacks the player.  Mod makers may want to change this, so this PR adds the following options:

Default - retail behavior
Friendly/Enemy (or Hostile) - display in the specified list regardless of who attacks whom
None - don't display in the hotkey list at all

This PR also slightly cleans up the hotkey list function with a small optimization and a few tweaky fixes for edge cases.
2020-04-15 13:47:11 -04:00
38 changed files with 973 additions and 516 deletions

No files matched your search

+2
View File
@@ -85,6 +85,8 @@ namespace AI {
Beams_damage_weapons,
Big_ships_can_attack_beam_turrets_on_untargeted_ships,
Disable_linked_fire_penalty,
Disable_player_secondary_doublefire,
Disable_ai_secondary_doublefire,
Disable_weapon_damage_scaling,
Dont_insert_random_turret_fire_delay,
Fix_ai_class_bug,
+4
View File
@@ -375,6 +375,10 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);
set_flag(profile, "$disable player secondary doublefire:", AI::Profile_Flags::Disable_player_secondary_doublefire);
set_flag(profile, "$disable ai secondary doublefire:", AI::Profile_Flags::Disable_ai_secondary_doublefire);
set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling);
set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity);
+3 -3
View File
@@ -12552,13 +12552,13 @@ int ai_acquire_emerge_path(object *pl_objp, int parent_objnum, int allowed_path_
polymodel *pm = model_get( Ship_info[parent_shipp->ship_info_index].model_num );
ship_bay *bay = pm->ship_bay;
if ( bay == NULL ) {
WarningEx(LOCATION, "Ship %s was set to arrive from fighter bay on object %s, but no fighter bay exists on that ships' model (%s).\n", shipp->ship_name, parent_shipp->ship_name, pm->filename);
if ( bay == nullptr ) {
Warning(LOCATION, "Ship %s was set to arrive from fighter bay on object %s, but no fighter bay exists on that ships' model (%s).\n", shipp->ship_name, parent_shipp->ship_name, pm->filename);
return -1;
}
if ( bay->num_paths <= 0 ) {
WarningEx(LOCATION, "Ship %s was set to arrive from fighter bay on object %s, but no fighter bay paths exist on that ships' model (%s).\n", shipp->ship_name, parent_shipp->ship_name, pm->filename);
Warning(LOCATION, "Ship %s was set to arrive from fighter bay on object %s, but no fighter bay paths exist on that ships' model (%s).\n", shipp->ship_name, parent_shipp->ship_name, pm->filename);
return -1;
}
+6 -11
View File
@@ -2544,7 +2544,6 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// Ok, the turret is lined up... now line up a particular gun.
bool ok_to_fire = false;
bool something_was_ok_to_fire=false;
vec3d tv2e; //so flak can get their jitter without screwing up other guns
if (in_fov ) {
@@ -2581,7 +2580,9 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
ss->turret_next_fire_pos = ffp_pos;
}
ship_get_global_turret_gun_info(&Objects[parent_objnum], ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
ship_get_global_turret_gun_info(&Objects[parent_objnum], ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
// Fire in the direction the turret is facing, not right at the target regardless of turret dir.
vm_vec_sub(&v2e, &predicted_enemy_pos, &gpos);
@@ -2592,12 +2593,6 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[0]);
else
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[i]);
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
// moved here as if there are two weapons with indentical fire stamps
// they would have shared the fire point.
tv2e = gvec;
// make sure to reset this for current weapon
ok_to_fire = false;
@@ -2605,7 +2600,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
flak_jitter_aim(&tv2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
flak_jitter_aim(&v2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
// Fire if:
@@ -2716,9 +2711,9 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
//Pass along which gun we are using
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &v2e, &predicted_enemy_pos);
else
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &v2e, &predicted_enemy_pos);
} else {
// make sure salvo fire mode does not turn into autofire
if ((tp->flags[Model::Subsystem_Flags::Turret_salvo]) && ((i + 1) == number_of_firings)) {
+63 -32
View File
@@ -162,8 +162,7 @@ Flag exe_params[] =
{ "-3dshockwave", "Enable 3D shockwaves", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
{ "-no_post_process", "Disable post-processing", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_post_process" },
{ "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
{ "-fxaa", "Enable FXAA anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fxaa" },
{ "-smaa", "Enable SMAA anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-smaa" },
{ "-aa", "Enable Post-process anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-aa" },
{ "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nolightshafts"},
{ "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
{ "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
@@ -322,10 +321,12 @@ cmdline_parm enable_3d_shockwave_arg("-3dshockwave", NULL, AT_NONE);
cmdline_parm softparticles_arg("-soft_particles", NULL, AT_NONE);
cmdline_parm no_postprocess_arg("-no_post_process", "Disables post-processing", AT_NONE);
cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires post-processing", AT_INT);
cmdline_parm fxaa_arg("-fxaa", NULL, AT_NONE);
cmdline_parm fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-9), requires post-processing and -fxaa", AT_INT);
cmdline_parm smaa_arg("-smaa", nullptr, AT_NONE);
cmdline_parm smaa_preset_arg("-smaa_preset", "SMAA quality (0-9), requires post-processing and -smaa", AT_INT);
cmdline_parm post_process_aa_arg("-aa", "Enables post-process antialiasing", AT_NONE);
cmdline_parm post_process_aa_preset_arg("-aa_preset", "Sets the AA effect to use. See the wiki for details", AT_INT);
cmdline_parm deprecated_fxaa_arg("-fxaa", nullptr, AT_NONE);
cmdline_parm deprecated_fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-2), requires post-processing and -fxaa", AT_INT);
cmdline_parm deprecated_smaa_arg("-smaa", nullptr, AT_NONE);
cmdline_parm deprecated_smaa_preset_arg("-smaa_preset", "SMAA quality (0-3), requires post-processing and -smaa", AT_INT);
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
@@ -1863,40 +1864,31 @@ bool SetCmdlineParams()
if ( height_arg.found() ) {
Cmdline_height = 0;
}
if (fxaa_arg.found() ) {
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
if (fxaa_preset_arg.found()) {
auto val = fxaa_preset_arg.get_int();
if (val > 6) {
Gr_aa_mode = AntiAliasMode::FXAA_High;
} else if (val > 3) {
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
} else {
if (post_process_aa_arg.found() || post_process_aa_preset_arg.found()) {
Gr_aa_mode = AntiAliasMode::SMAA_Low;
if (post_process_aa_preset_arg.found()) {
switch (post_process_aa_preset_arg.get_int()) {
case 0:
Gr_aa_mode = AntiAliasMode::FXAA_Low;
}
}
}
if (smaa_arg.found()) {
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
if (smaa_preset_arg.found()) {
switch (smaa_preset_arg.get_int()) {
case 0:
break;
case 1:
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
break;
case 2:
Gr_aa_mode = AntiAliasMode::FXAA_High;
break;
case 3:
Gr_aa_mode = AntiAliasMode::SMAA_Low;
break;
case 1:
case 4:
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
break;
case 2:
case 5:
Gr_aa_mode = AntiAliasMode::SMAA_High;
break;
case 3:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
default:
case 6:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
}
@@ -2210,6 +2202,45 @@ bool SetCmdlineParams()
if (deprecated_postprocess_arg.found()) {
Cmdline_deprecated_postprocess = true;
}
if (deprecated_fxaa_arg.found() ) {
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
if (deprecated_fxaa_preset_arg.found()) {
auto val = deprecated_fxaa_preset_arg.get_int();
if (val > 6) {
Gr_aa_mode = AntiAliasMode::FXAA_High;
} else if (val > 3) {
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
} else {
Gr_aa_mode = AntiAliasMode::FXAA_Low;
}
}
}
if (deprecated_smaa_arg.found()) {
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
if (deprecated_smaa_preset_arg.found()) {
switch (deprecated_smaa_preset_arg.get_int()) {
case 0:
Gr_aa_mode = AntiAliasMode::SMAA_Low;
break;
case 1:
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
break;
case 2:
Gr_aa_mode = AntiAliasMode::SMAA_High;
break;
case 3:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
default:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
}
}
}
return true;
}
+1 -1
View File
@@ -70,7 +70,7 @@
// from weapon.h
#define MAX_WEAPONS 2000
#define MAX_WEAPON_TYPES 300
#define MAX_WEAPON_TYPES 500
// from model.h
+19 -15
View File
@@ -254,25 +254,29 @@ void gr_opengl_post_process_begin()
Post_in_frame = true;
}
SCP_vector<shader_type> get_aa_shader_types(AntiAliasMode aa_mode) {
auto stypes = SCP_vector<shader_type>();
if (gr_is_fxaa_mode(aa_mode)) {
stypes.push_back(shader_type::SDR_TYPE_POST_PROCESS_FXAA);
}
else if (gr_is_smaa_mode(aa_mode)) {
stypes.push_back(shader_type::SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT);
stypes.push_back(shader_type::SDR_TYPE_POST_PROCESS_SMAA_EDGE);
stypes.push_back(shader_type::SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING);
}
return stypes;
}
void recompile_aa_shader() {
auto stype = SCP_vector<shader_type>();
if (gr_is_fxaa_mode(Gr_aa_mode)) {
stype.push_back(shader_type::SDR_TYPE_POST_PROCESS_FXAA);
}
else if (gr_is_smaa_mode(Gr_aa_mode)) {
stype.push_back(shader_type::SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT);
stype.push_back(shader_type::SDR_TYPE_POST_PROCESS_SMAA_EDGE);
stype.push_back(shader_type::SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING);
}
mprintf(("Recompiling AA shader(s)...\n"));
for (auto sdr : stype) {
// start recompile by grabbing deleting the current shader we have, assuming it's already created
for (auto sdr : get_aa_shader_types(Gr_aa_mode_last_frame)) {
opengl_delete_shader( gr_opengl_maybe_create_shader(sdr, 0) );
}
// then recreate it again. shader loading code will be updated with the new AA presets
for (auto sdr : get_aa_shader_types(Gr_aa_mode)) {
gr_opengl_maybe_create_shader(sdr, 0);
}
@@ -1251,7 +1255,7 @@ static bool opengl_post_init_framebuffer()
opengl_setup_bloom_textures();
if (gr_is_smaa_mode(Gr_aa_mode)) {
if (Gr_aa_mode != AntiAliasMode::None) {
setup_smaa_resources();
}
+13 -5
View File
@@ -3975,12 +3975,14 @@ void HudGaugeLeadIndicator::renderLeadCurrentTarget()
}
frame_offset = pickFrame(prange, srange, dist_to_target);
if ( frame_offset < 0 ) {
if ( frame_offset < 0 && srange != -1.0f ) {
return;
}
hud_calculate_lead_pos(&lead_target_pos, &target_pos, targetp, wip, dist_to_target);
renderIndicator(frame_offset, targetp, &lead_target_pos);
if (frame_offset >= 0) {
hud_calculate_lead_pos(&lead_target_pos, &target_pos, targetp, wip, dist_to_target);
renderIndicator(frame_offset, targetp, &lead_target_pos);
}
//do dumbfire lead indicator - color is orange (255,128,0) - bright, (192,96,0) - dim
//phreak changed 9/01/02
@@ -6074,7 +6076,10 @@ void HudGaugeWeapons::render(float /*frametime*/)
renderPrintf(position[0] + Weapon_sunlinked_offset_x, name_y, EG_NULL, "%c", Weapon_link_icon);
// indicate if this is linked
if ( Player_ship->flags[Ship::Ship_Flags::Secondary_dual_fire] ) {
// don't draw the link indicator if the fire can't be fired link.
// the link flag is ignored rather than cleared so the player can cycle past a no-doublefire weapon without the setting being cleared
if ( Player_ship->flags[Ship::Ship_Flags::Secondary_dual_fire] && !wip->wi_flags[Weapon::Info_Flags::No_doublefire] &&
!The_mission.ai_profile->flags[AI::Profile_Flags::Disable_player_secondary_doublefire] ) {
renderPrintf(position[0] + Weapon_slinked_offset_x, name_y, EG_NULL, "%c", Weapon_link_icon);
}
@@ -6992,7 +6997,10 @@ void HudGaugeSecondaryWeapons::render(float /*frametime*/)
renderPrintf(position[0] + _sunlinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
// indicate if this is linked
if ( Player_ship->flags[Ship::Ship_Flags::Secondary_dual_fire] ) {
// don't draw the link indicator if the fire can't be fired link.
// the link flag is ignored rather than cleared so the player can cycle past a no-doublefire weapon without the setting being cleared
if ( Player_ship->flags[Ship::Ship_Flags::Secondary_dual_fire] && !wip->wi_flags[Weapon::Info_Flags::No_doublefire] &&
!The_mission.ai_profile->flags[AI::Profile_Flags::Disable_player_secondary_doublefire] ) {
renderPrintf(position[0] + _slinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
}
+20 -7
View File
@@ -360,6 +360,23 @@ void iff_init()
num_observed_colors[cur_iff]++;
}
// get F3 override
iff->hotkey_team = IFF_hotkey_team::Default;
if (optional_string("+Hotkey Team:"))
{
char temp[NAME_LENGTH];
stuff_string(temp, F_NAME, NAME_LENGTH);
if (!stricmp(temp, "Friendly"))
iff->hotkey_team = IFF_hotkey_team::Friendly;
else if (!stricmp(temp, "Hostile") || !stricmp(temp, "Enemy"))
iff->hotkey_team = IFF_hotkey_team::Hostile;
else if (!stricmp(temp, "None"))
iff->hotkey_team = IFF_hotkey_team::None;
else
Warning(LOCATION, "Unrecognized +Hotkey Tean: %s\n", temp);
}
// get flags ----------------------------------------------------------
@@ -560,10 +577,8 @@ int iff_get_attacker_mask(int attackee_team)
*
* @param team_x Team of attacker
* @param team_y Team of attackee
*
* @return >0 if true, 0 if false
*/
int iff_x_attacks_y(int team_x, int team_y)
bool iff_x_attacks_y(int team_x, int team_y)
{
return iff_matches_mask(team_y, iff_get_attackee_mask(team_x));
}
@@ -583,12 +598,10 @@ int iff_get_mask(int team)
*
* @param team Team to test
* @param mask Mask
*
* @return 1 if matches, 0 if does not match
*/
int iff_matches_mask(int team, int mask)
bool iff_matches_mask(int team, int mask)
{
return (iff_get_mask(team) & mask) ? 1 : 0;
return (iff_get_mask(team) & mask) != 0;
}
/**
+5 -2
View File
@@ -22,6 +22,8 @@ class object;
#define IFF_COLOR_TAGGED 2
#define MAX_IFF_COLORS (MAX_IFFS + 3)
enum IFF_hotkey_team { Default = -1, None = 0, Friendly, Hostile };
// iff flags
#define IFFF_SUPPORT_ALLOWED (1 << 0) // this IFF can call for support
#define IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR (1 << 1) // self-explanatory
@@ -41,6 +43,7 @@ typedef struct iff_info {
int attackee_bitmask; // treat this as private and use iff_get_attackee_mask or iff_x_attacks_y
int attackee_bitmask_all_teams_at_war; // treat this as private and use iff_get_attackee_mask or iff_x_attacks_y
int observed_color_index[MAX_IFFS]; // treat this as private and use iff_get_color or iff_get_color_by_team
IFF_hotkey_team hotkey_team;
// flags
int flags;
@@ -74,11 +77,11 @@ extern int iff_lookup(const char *iff_name);
// If he fires at you, you don't react unless you are coded to attack him, because you are oblivious.
extern int iff_get_attackee_mask(int attacker_team);
extern int iff_get_attacker_mask(int attackee_team);
extern int iff_x_attacks_y(int team_x, int team_y);
extern bool iff_x_attacks_y(int team_x, int team_y);
// mask stuff
extern int iff_get_mask(int team);
extern int iff_matches_mask(int team, int mask);
extern bool iff_matches_mask(int team, int mask);
// get color stuff
extern color *iff_get_color(int color_index, int is_bright);
+52
View File
@@ -17,6 +17,7 @@
#include "io/joy.h"
#include "io/timer.h"
#include "ship/ship.h"
#include "ship/ship_flags.h"
#include "playerman/player.h"
#include "weapon/weapon.h"
#include "hud/hud.h"
@@ -1095,6 +1096,57 @@ void process_debug_keys(int k)
break;
}
// Goober5000
case KEY_DEBUGGED + KEY_SHIFTED + KEY_R:
case KEY_DEBUGGED1 + KEY_SHIFTED + KEY_R:
{
// toggle support for this mission
if (The_mission.support_ships.max_support_ships == 0)
{
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR("Setting maximum number of support ships to infinite.", 1643));
The_mission.support_ships.max_support_ships = -1;
}
else
{
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR("Setting maximum number of support ships to zero.", 1644));
The_mission.support_ships.max_support_ships = 0;
}
break;
}
// Goober5000
case KEY_DEBUGGED + KEY_SHIFTED + KEY_U:
case KEY_DEBUGGED1 + KEY_SHIFTED + KEY_U:
{
// toggle the current target between scanned and unscanned
if (Player_ai->target_objnum >= 0)
{
object *objp = &Objects[Player_ai->target_objnum];
if (objp->type == OBJ_SHIP)
{
ship *targeted_shipp = &Ships[objp->instance];
if (Player_ai->targeted_subsys == nullptr)
{
if (targeted_shipp->flags[Ship::Ship_Flags::Cargo_revealed])
ship_do_cargo_hidden(targeted_shipp);
else
ship_do_cargo_revealed(targeted_shipp);
}
else
{
if (Player_ai->targeted_subsys->flags[Ship::Subsystem_Flags::Cargo_revealed])
ship_do_cap_subsys_cargo_hidden(targeted_shipp, Player_ai->targeted_subsys);
else
ship_do_cap_subsys_cargo_revealed(targeted_shipp, Player_ai->targeted_subsys);
}
}
}
break;
}
case KEY_DEBUGGED + KEY_SHIFTED + KEY_UP:
Game_detail_level++;
HUD_printf( XSTR( "Detail level set to %+d\n", 22), Game_detail_level );
+28
View File
@@ -440,6 +440,13 @@ void labviewer_render_model(float frametime)
ship_model_update_instance(obj);
Ships[obj->instance].team_name = Lab_team_color;
if (Lab_viewer_flags & LAB_FLAG_LIGHTNING_ARCS) {
obj->hull_strength = 1.0f;
}
else {
obj->hull_strength = Ship_info[Ships[obj->instance].ship_info_index].max_hull_strength;
}
}
if (Lab_render_wireframe)
@@ -1575,6 +1582,27 @@ void labviewer_change_ship_lod(Tree* caller)
Lab_selected_object = ship_create(&vmd_identity_matrix, &Lab_model_pos, ship_index);
Objects[Lab_selected_object].flags.set(Object::Object_Flags::Player_ship);
auto ship_objp = &Ships[Objects[Lab_selected_object].instance];
auto ship_infop = &Ship_info[ship_objp->ship_info_index];
// If the ship class defines replacement textures, load them and apply them to the ship
// load the texture
auto replacements = SCP_vector<texture_replace>();
for (auto tr : ship_infop->replacement_textures) {
if (!stricmp(tr.new_texture, "invisible"))
{
// invisible is a special case
tr.new_texture_id = REPLACE_WITH_INVISIBLE;
}
else
{
// try to load texture or anim as normal
tr.new_texture_id = bm_load_either(tr.new_texture);
}
replacements.push_back(tr);
}
ship_objp->apply_replacement_textures(replacements);
lab_cam_distance = Objects[Lab_selected_object].radius * 1.6f;
+89 -30
View File
@@ -48,6 +48,8 @@ int Lcl_gr = 0;
int Lcl_pl = 0;
int Lcl_english = 1;
bool *Lcl_unexpected_tstring_check = nullptr;
// executable string localization data --------------------
@@ -56,7 +58,7 @@ int Lcl_english = 1;
// the english version (in the code) to a foreign version (in the table). Thus, if you
// add a new string to the code, you must assign it a new index. Use the number below for
// that index and increase the number below by one.
#define XSTR_SIZE 1643
#define XSTR_SIZE 1645
// struct to allow for strings.tbl-determined x offset
@@ -626,15 +628,18 @@ void lcl_fred_replace_stuff(SCP_string &text)
// XSTR("whee", 20)
// and these should cover all the externalized string cases
// fills in id if non-NULL. a value of -2 indicates it is not an external string
void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
// returns true if we were able to extract the XSTR elements (text_str and maybe id are populated)
bool lcl_ext_localize_sub(const char *in, char *text_str, char *out, size_t max_len, int *id)
{
char text_str[PARSE_BUF_SIZE]="";
int str_id;
size_t str_len;
Assert(in);
Assert(out);
// NOTE: "Token too long" warnings are disabled when Lcl_unexpected_tstring_check is active,
// because in such cases we actually anticipate that the length might be exceeded.
// default (non-external string) value
if (id != NULL) {
*id = -2;
@@ -644,7 +649,7 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
// if the string is < 9 chars, it can't be an XSTR("",) tag, so just copy it
if (str_len < 9) {
if (str_len > max_len)
if (str_len > max_len && !Lcl_unexpected_tstring_check)
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", in, str_len, max_len);
strncpy(out, in, max_len);
@@ -652,13 +657,13 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
if (id != NULL)
*id = -2;
return;
return false;
}
// otherwise, check to see if it's an XSTR() tag
if (strnicmp(in, "XSTR", 4) != 0) {
// NOT an XSTR() tag
if (str_len > max_len)
if (str_len > max_len && !Lcl_unexpected_tstring_check)
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", in, str_len, max_len);
strncpy(out, in, max_len);
@@ -666,12 +671,12 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
if (id != NULL)
*id = -2;
return;
return false;
}
// at this point we _know_ its an XSTR() tag, so split off the strings and id sections
if (!lcl_ext_get_text(in, text_str)) {
if (str_len > max_len)
if (str_len > max_len && !Lcl_unexpected_tstring_check)
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", in, str_len, max_len);
strncpy(out, in, max_len);
@@ -679,10 +684,10 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
if (id != NULL)
*id = -1;
return;
return false;
}
if (!lcl_ext_get_id(in, &str_id)) {
if (str_len > max_len)
if (str_len > max_len && !Lcl_unexpected_tstring_check)
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", in, str_len, max_len);
strncpy(out, in, max_len);
@@ -690,12 +695,12 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
if (id != NULL)
*id = -1;
return;
return false;
}
// if the localization file is not open, or we're running in the default language, return the original string
if ( !Xstr_inited || (str_id < 0) || (Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE) ) {
if ( strlen(text_str) > max_len )
// if the localization file is not open, or there's no entry, return the original string
if ( !Xstr_inited || (str_id < 0) ) {
if ( strlen(text_str) > max_len && !Lcl_unexpected_tstring_check )
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", text_str, strlen(text_str), max_len);
strncpy(out, text_str, max_len);
@@ -703,20 +708,20 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
if (id != NULL)
*id = str_id;
return;
return true;
}
// get the string if it exists
if (Lcl_ext_str.find(str_id) != Lcl_ext_str.end()) {
// copy to the outgoing string
if ( strlen(Lcl_ext_str[str_id]) > max_len )
if ( strlen(Lcl_ext_str[str_id]) > max_len && !Lcl_unexpected_tstring_check )
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", Lcl_ext_str[str_id], strlen(Lcl_ext_str[str_id]), max_len);
strncpy(out, Lcl_ext_str[str_id], max_len);
}
// otherwise use what we have - probably should Int3() or assert here
else {
if ( strlen(text_str) > max_len )
if ( strlen(text_str) > max_len && !Lcl_unexpected_tstring_check )
error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".\n", text_str, strlen(text_str), max_len);
strncpy(out, text_str, max_len);
@@ -726,12 +731,13 @@ void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
if (id != NULL) {
*id = str_id;
}
return true;
}
// ditto for SCP_string
void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
bool lcl_ext_localize_sub(const SCP_string &in, SCP_string &text_str, SCP_string &out, int *id)
{
SCP_string text_str = "";
int str_id;
// default (non-external string) value
@@ -746,7 +752,7 @@ void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
if (id != NULL)
*id = -2;
return;
return false;
}
// otherwise, check to see if it's an XSTR() tag
@@ -757,7 +763,7 @@ void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
if (id != NULL)
*id = -2;
return;
return false;
}
// at this point we _know_ its an XSTR() tag, so split off the strings and id sections
@@ -767,7 +773,7 @@ void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
if (id != NULL)
*id = -1;
return;
return false;
}
if (!lcl_ext_get_id(in, &str_id)) {
out = in;
@@ -775,17 +781,17 @@ void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
if (id != NULL)
*id = -1;
return;
return false;
}
// if the localization file is not open, or we're running in the default language, return the original string
if ( !Xstr_inited || (str_id < 0) || (Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE) ) {
// if the localization file is not open, or there's no entry, return the original string
if ( !Xstr_inited || (str_id < 0) ) {
out = text_str;
if (id != NULL)
*id = str_id;
return;
return true;
}
// get the string if it exists
@@ -802,15 +808,43 @@ void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
if (id != NULL){
*id = str_id;
}
return true;
}
// Goober5000 - wrapper for lcl_ext_localize_sub; used because lcl_replace_stuff has to
// be called *after* the translation is done, and the original function returned in so
// many places that it would be messy to call lcl_replace_stuff everywhere
// Addendum: Now, of course, it provides a handy way to encapsulate the unexpected tstring check.
void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id)
{
// do XSTR translation
lcl_ext_localize_sub(in, out, max_len, id);
// buffer for the untranslated string inside the XSTR tag
char text_str[PARSE_BUF_SIZE] = "";
// if we're doing this extra check, then we have to compare the untranslated string with the default language string and see if they're different
if (Lcl_unexpected_tstring_check)
{
int saved_language = Lcl_current_lang;
Lcl_current_lang = FS2_OPEN_DEFAULT_LANGUAGE;
bool extracted = lcl_ext_localize_sub(in, text_str, out, max_len, id);
// the untranslated and default-translated strings should always be identical, so if they're different, it might mean we have some data from a different mod
if (extracted && strcmp(text_str, out) != 0)
*Lcl_unexpected_tstring_check = true;
// at this point, we go back to our usual language and do the translation for real
if (saved_language != Lcl_current_lang)
{
Lcl_current_lang = saved_language;
lcl_ext_localize_sub(in, text_str, out, max_len, id);
}
}
// most of the time we're not going to do the check, so localize as normal
else
{
// do XSTR translation
lcl_ext_localize_sub(in, text_str, out, max_len, id);
}
// do translation of $callsign, $rank, etc.
lcl_replace_stuff(out, max_len);
@@ -819,8 +853,33 @@ void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id)
// ditto for SCP_string
void lcl_ext_localize(const SCP_string &in, SCP_string &out, int *id)
{
// do XSTR translation
lcl_ext_localize_sub(in, out, id);
// buffer for the untranslated string inside the XSTR tag
SCP_string text_str = "";
// if we're doing this extra check, then we have to compare the untranslated string with the default language string and see if they're different
if (Lcl_unexpected_tstring_check)
{
int saved_language = Lcl_current_lang;
Lcl_current_lang = FS2_OPEN_DEFAULT_LANGUAGE;
bool extracted = lcl_ext_localize_sub(in, text_str, out, id);
// the untranslated and default-translated strings should always be identical, so if they're different, it might mean we have some data from a different mod
if (extracted && text_str != out)
*Lcl_unexpected_tstring_check = true;
// at this point, we go back to our usual language and do the translation for real
if (saved_language != Lcl_current_lang)
{
Lcl_current_lang = saved_language;
lcl_ext_localize_sub(in, text_str, out, id);
}
}
// most of the time we're not going to do the check, so localize as normal
else
{
// do XSTR translation
lcl_ext_localize_sub(in, text_str, out, id);
}
// do translation of $callsign, $rank, etc.
lcl_replace_stuff(out);
+5 -2
View File
@@ -61,6 +61,9 @@ extern int Lcl_english;
// The currently active language. Index into Lcl_languages.
extern int Lcl_current_lang;
// special check for misplaced mod data (see Mantis #2942)
extern bool *Lcl_unexpected_tstring_check;
// ------------------------------------------------------------------------------------------------------------
// LOCALIZE FUNCTIONS
@@ -110,8 +113,8 @@ void lcl_fred_replace_stuff(SCP_string &text);
// XSTR("whee", 20)
// and these should cover all the externalized string cases
// fills in id if non-NULL. a value of -2 indicates it is not an external string
void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id = NULL);
void lcl_ext_localize(const SCP_string &in, SCP_string &out, int *id = NULL);
void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id = nullptr);
void lcl_ext_localize(const SCP_string &in, SCP_string &out, int *id = nullptr);
// translate the specified string based upon the current language
const char *XSTR(const char *str, int index);
+21 -2
View File
@@ -450,6 +450,7 @@ int build_standalone_mission_list_do_frame()
int font_height = gr_get_font_height();
char filename[MAX_FILENAME_LEN];
char str[256];
bool lcl_weirdness = false;
// When no standalone missions in data directory
if (Num_standalone_missions == 0) {
@@ -473,8 +474,16 @@ int build_standalone_mission_list_do_frame()
// tack on an extension
strcat_s(filename, FS_MISSION_FILE_EXT);
// check if we can list the mission and if loading basic info didn't return an error code
if (!mission_is_ignored(filename) && !get_mission_info(filename)) {
// activate tstrings check
Lcl_unexpected_tstring_check = &lcl_weirdness;
// check if we can list the mission, if loading basic info didn't return an error code, and if we didn't find an unexpected XSTR mismatch
bool condition = !mission_is_ignored(filename) && !get_mission_info(filename) && !lcl_weirdness;
// deactivate tstrings check
Lcl_unexpected_tstring_check = nullptr;
if (condition) {
Standalone_mission_names[Num_standalone_missions_with_info] = vm_strdup(The_mission.name);
Standalone_mission_flags[Num_standalone_missions_with_info] = The_mission.game_type;
int y = Num_lines * (font_height + 2);
@@ -1099,7 +1108,17 @@ void sim_room_init()
memset(wild_card, 0, 256);
strcpy_s(wild_card, NOX("*"));
strcat_s(wild_card, FS_MISSION_FILE_EXT);
#ifndef NDEBUG
// Activate the check while we fill the mission list so that we don't potentially end up with dozens of string length warnings.
// We don't actually remove mismatched missions from the list here; that will happen in build_standalone_mission_list_do_frame().
bool dummy_buffer;
Lcl_unexpected_tstring_check = &dummy_buffer;
#endif
Num_standalone_missions = cf_get_file_list(MAX_MISSIONS, Mission_filenames, CF_TYPE_MISSIONS, wild_card, CF_SORT_NAME);
#ifndef NDEBUG
Lcl_unexpected_tstring_check = nullptr;
#endif
// set up slider with 0 items to start
Sim_room_slider.create(&Ui_window, Sim_room_slider_coords[gr_screen.res][X_COORD], Sim_room_slider_coords[gr_screen.res][Y_COORD], Sim_room_slider_coords[gr_screen.res][W_COORD], Sim_room_slider_coords[gr_screen.res][H_COORD], 0, Sim_room_slider_filename[gr_screen.res], &sim_room_scroll_screen_up, &sim_room_scroll_screen_down, &sim_room_scroll_capture);
+52 -18
View File
@@ -569,63 +569,88 @@ int hotkey_build_team_listing(int enemy_team_mask, int y, bool list_enemies)
const char *str = NULL;
int i, j, s, z, start, team_mask;
int font_height = gr_get_font_height();
IFF_hotkey_team hotkey_team;
if (list_enemies)
{
str = XSTR( "Enemy ships", 403);
team_mask = enemy_team_mask;
hotkey_team = IFF_hotkey_team::Hostile;
}
else
{
str = XSTR( "Friendly ships", 402);
team_mask = ~enemy_team_mask;
hotkey_team = IFF_hotkey_team::Friendly;
}
for (i=0; i<MAX_SHIPS; i++)
if (iff_matches_mask(Ships[i].team, team_mask))
break;
if (i >= MAX_SHIPS)
return y;
hotkey_line_add(str, HOTKEY_LINE_HEADING, 0, y);
y += 2;
start = Num_lines;
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
int shipnum;
bool add_it;
// don't process non-ships, or the player ship
if ( (Game_mode & GM_NORMAL) && (so->objnum == OBJ_INDEX(Player_obj)) )
continue;
shipnum = Objects[so->objnum].instance;
int shipnum = Objects[so->objnum].instance;
ship *shipp = &Ships[shipnum];
// filter out ships in wings
if ( shipp->wingnum >= 0 )
continue;
// filter out cargo containers, navbouys, etc, and non-ships
if ( Ship_info[Ships[shipnum].ship_info_index].class_type < 0 || !(Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::Hotkey_on_list] ))
if ( Ship_info[shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Hotkey_on_list]) )
continue;
// don't process ships invisible to sensors, dying or departing
if ( Ships[shipnum].flags[Ship::Ship_Flags::Hidden_from_sensors] || Ships[shipnum].is_dying_or_departing() )
if ( shipp->flags[Ship::Ship_Flags::Hidden_from_sensors] || shipp->is_dying_or_departing() )
continue;
// if a ship's hotkey is the last hotkey on the list, then maybe make the hotkey -1 if
// we are now in mission. Otherwise, skip this ship
if ( Ships[shipnum].hotkey == MAX_KEYED_TARGETS ) {
if ( shipp->hotkey == MAX_KEYED_TARGETS ) {
if ( !(Game_mode & GM_IN_MISSION) )
continue; // skip to next ship
Ships[shipnum].hotkey = -1;
shipp->hotkey = -1;
}
// be sure this ship isn't in a wing, and that the teams match
if ( iff_matches_mask(Ships[shipnum].team, team_mask) && (Ships[shipnum].wingnum < 0) ) {
hotkey_line_add_sorted(Ships[shipnum].get_display_string(), HOTKEY_LINE_SHIP, shipnum, start);
// check IFF override and team mask
if (Iff_info[shipp->team].hotkey_team == IFF_hotkey_team::Default) {
add_it = iff_matches_mask(shipp->team, team_mask);
} else {
add_it = (Iff_info[shipp->team].hotkey_team == hotkey_team);
}
// add it if the teams match or if the IFF says to
if (add_it) {
hotkey_line_add_sorted(shipp->get_display_string(), HOTKEY_LINE_SHIP, shipnum, start);
}
}
for (i=0; i<Num_wings; i++) {
if (Wings[i].current_count && (Wings[i].ship_index[Wings[i].special_ship] >= 0) && iff_matches_mask(Ships[Wings[i].ship_index[Wings[i].special_ship]].team, team_mask)) {
bool add_it;
// the wing has to be valid
if (Wings[i].current_count && Wings[i].ship_index[Wings[i].special_ship] >= 0) {
ship *shipp = &Ships[Wings[i].ship_index[Wings[i].special_ship]];
// check IFF override and team mask
if (Iff_info[shipp->team].hotkey_team == IFF_hotkey_team::Default) {
add_it = iff_matches_mask(shipp->team, team_mask);
} else {
add_it = (Iff_info[shipp->team].hotkey_team == hotkey_team);
}
} else {
add_it = false;
}
// add it if the teams match or if the IFF says to
if (add_it) {
// special check for the player's wing. If he's in a wing, and the only guy left, don't
// do anything
if ( (Player_ship->wingnum == i) && (Wings[i].current_count == 1) )
@@ -652,12 +677,21 @@ int hotkey_build_team_listing(int enemy_team_mask, int y, bool list_enemies)
if (Wings[i].flags[Ship::Wing_Flags::Expanded]) {
for (j=0; j<Wings[i].current_count; j++) {
s = Wings[i].ship_index[j];
z = hotkey_line_insert(z + 1, Ships[s].get_display_string(), HOTKEY_LINE_SUBSHIP, s);
if (!Ships[s].is_dying_or_departing()) {
z = hotkey_line_insert(z + 1, Ships[s].get_display_string(), HOTKEY_LINE_SUBSHIP, s);
}
}
}
}
}
// see if we actually added any lines
if (start == Num_lines) {
// roll back the heading, then return as if nothing happened
Num_lines--;
return y - 2;
}
for (i=start; i<Num_lines; i++) {
if (Hotkey_lines[i].type == HOTKEY_LINE_SUBSHIP)
y += font_height;
+2 -1
View File
@@ -625,6 +625,7 @@ void parse_msgtbl()
generic_message_filenames.clear();
generic_message_filenames.push_back("none");
generic_message_filenames.push_back("cuevoice");
generic_message_filenames.push_back("cue_voice");
generic_message_filenames.push_back("emptymsg");
generic_message_filenames.push_back("generic");
generic_message_filenames.push_back("msgstart");
@@ -1145,7 +1146,7 @@ void message_calc_anim_start_frame(int time, generic_anim *ani, int reverse)
}
if ( start_frame < 0 ) {
Int3();
mprintf(("Calculated start frame for animation %s was less than 0, setting to 0.", ani->filename));
start_frame=0;
}
+23 -30
View File
@@ -60,6 +60,7 @@
#include "object/waypoint.h"
#include "parse/generic_log.h"
#include "parse/parselo.h"
#include "scripting/hook_api.h"
#include "scripting/scripting.h"
#include "playerman/player.h"
#include "popup/popup.h"
@@ -406,6 +407,11 @@ void convertFSMtoFS2();
MONITOR(NumShipArrivals)
MONITOR(NumShipDepartures)
const std::shared_ptr<scripting::Hook> OnDepartureStartedHook = scripting::Hook::Factory(
"On Departure Started", "Called when a ship starts the departure process.",
{
{"Ship", "ship", "The ship that has began the depture process."},
});
// Goober5000
void parse_custom_bitmap(const char *expected_string_640, const char *expected_string_1024, char *string_field_640, char *string_field_1024)
@@ -2024,29 +2030,7 @@ int parse_create_object_sub(p_object *p_objp)
shipp->base_texture_anim_frametime = game_get_overall_frametime();
// handle the replacement textures
if (!p_objp->replacement_textures.empty())
{
shipp->ship_replacement_textures = (int *) vm_malloc( MAX_REPLACEMENT_TEXTURES * sizeof(int));
for (i = 0; i < MAX_REPLACEMENT_TEXTURES; i++)
shipp->ship_replacement_textures[i] = -1;
}
// now fill them in
for (SCP_vector<texture_replace>::iterator tr = p_objp->replacement_textures.begin(); tr != p_objp->replacement_textures.end(); ++tr)
{
pm = model_get(sip->model_num);
// look for textures
for (j = 0; j < pm->n_textures; j++)
{
texture_map *tmap = &pm->maps[j];
int tnum = tmap->FindTexture(tr->old_texture);
if(tnum > -1)
shipp->ship_replacement_textures[j * TM_NUM_TYPES + tnum] = tr->new_texture_id;
}
}
shipp->apply_replacement_textures(p_objp->replacement_textures);
// Copy across the alt classes (if any) for FRED
if (Fred_running) {
@@ -6011,15 +5995,18 @@ void parse_init(bool basic)
{
reset_parse();
for (int i = 0; i < MAX_CARGO; i++)
Cargo_names[i] = Cargo_names_buf[i]; // make a pointer array for compatibility
// if we just want basic info then we don't need some of this initialization
if (!basic)
{
for (int i = 0; i < MAX_CARGO; i++)
Cargo_names[i] = Cargo_names_buf[i]; // make a pointer array for compatibility
Total_goal_target_names = 0;
Total_goal_target_names = 0;
// if we are just wanting basic info then we shouldn't need sexps
// (prevents memory fragmentation with the now dynamic Sexp_nodes[])
if ( !basic )
// if we are just wanting basic info then we shouldn't need sexps
// (prevents memory fragmentation with the now dynamic Sexp_nodes[])
init_sexp();
}
}
// main parse routine for parsing a mission. The default parameter flags tells us which information
@@ -6643,7 +6630,8 @@ int mission_set_arrival_location(int anchor, int location, int dist, int objnum,
// if we get an error, just let the ship arrive(?)
if ( ai_acquire_emerge_path(&Objects[objnum], anchor_objnum, path_mask, &pos, &fvec) == -1 ) {
Int3(); // get MWA or AL -- not sure what to do here when we cannot acquire a path
// get MWA or AL -- not sure what to do here when we cannot acquire a path
mprintf(("Unable to acquire arrival path on anchor ship %s\n", Ships[shipnum].ship_name));
return -1;
}
Objects[objnum].pos = pos;
@@ -7143,6 +7131,11 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
mprintf(("Entered mission_do_departure() for %s\n", shipp->ship_name));
// add scripting hook for 'On Depature Started' --wookieejedi
// hook is placed at the begining of this function to allow the scripter to
// actually have access to the ship's departure decisions before they are all executed
OnDepartureStartedHook->run(scripting::hook_param_list(scripting::hook_param("Ship", 'o', objp)));
// abort rearm, because if we entered this function we're either going to depart via hyperspace, depart via bay,
// or revert to our default behavior
ai_abort_rearm_request(objp);
+1 -1
View File
@@ -1992,7 +1992,7 @@ int brief_only_allow_briefing()
return 1;
}
if ( The_mission.flags[Mission::Mission_Flags::Scramble] || The_mission.flags[Mission::Mission_Flags::Red_alert] ) {
if ( The_mission.flags[Mission::Mission_Flags::Scramble, Mission::Mission_Flags::Red_alert] ) {
return 1;
}
+8 -3
View File
@@ -1860,6 +1860,11 @@ bool is_a_weapon_slot_empty()
// a ship must exist in this slot
if (Wss_slots[slot].ship_class >= 0)
{
// if the player can't modify the weapons, then an empty bank is not his fault
auto ss_slot = &Ss_wings[slot / MAX_WING_SLOTS].ss_slots[slot % MAX_WING_SLOTS];
if (ss_slot->status & WING_SLOT_WEAPONS_DISABLED)
continue;
ship_info *sip = &Ship_info[Wss_slots[slot].ship_class];
// check primary banks
@@ -1874,7 +1879,7 @@ bool is_a_weapon_slot_empty()
for (int bank = 0; bank < sip->num_secondary_banks; ++bank)
{
// is the slot empty?
if (Wss_slots[slot].wep_count[MAX_SHIP_PRIMARY_BANKS+bank] <= 0)
if (Wss_slots[slot].wep_count[MAX_SHIP_PRIMARY_BANKS + bank] <= 0)
return true;
}
}
@@ -1953,7 +1958,7 @@ void commit_pressed()
// Goober5000 - check that all weapon slots are filled (Mantis 2715)
// Note: don't check for training, scramble, or red-alert missions
// Note2: don't check missions without briefings either
if (is_a_weapon_slot_empty() && !(The_mission.game_type & MISSION_TYPE_TRAINING) && !The_mission.flags[Mission::Mission_Flags::Scramble] && !The_mission.flags[Mission::Mission_Flags::Red_alert] && !The_mission.flags[Mission::Mission_Flags::No_briefing])
if (is_a_weapon_slot_empty() && !(The_mission.game_type & MISSION_TYPE_TRAINING) && !The_mission.flags[Mission::Mission_Flags::Scramble, Mission::Mission_Flags::Red_alert, Mission::Mission_Flags::No_briefing])
{
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("At least one ship has an empty weapon bank. All weapon banks must have weapons assigned.", 1642), weapon_list.c_str());
return;
@@ -2197,7 +2202,7 @@ void draw_wing_block(int wb_num, int hot_slot, int selected_slot, int class_sele
color_to_draw = &Icon_colors[ICON_FRAME_DISABLED];
// in multiplayer, determine if this it the special case where the slot is disabled, and
// it is also _my_ slot (ie, team capatains/host have not locked players yet)
// it is also _my_ slot (ie, team captains/hosts have not locked players yet)
if((Game_mode & GM_MULTIPLAYER) && multi_ts_disabled_high_slot(slot_index)){
if(icon->model_index == -1)
bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_DISABLED_HIGH];
+1 -1
View File
@@ -371,7 +371,7 @@ typedef struct mp_vert {
} mp_vert;
typedef struct model_path {
char name[MAX_NAME_LEN]; // name of the subsystem. Probably displayed on HUD
char name[MAX_NAME_LEN]; // name of the path. Should be unique
char parent_name[MAX_NAME_LEN]; // parent name of submodel that path is linked to in POF
int parent_submodel;
int nverts;
+21 -1
View File
@@ -2273,7 +2273,15 @@ int read_model_file(polymodel * pm, const char *filename, int n_subsystems, mode
memset( pm->paths, 0, sizeof(model_path) * pm->n_paths );
for (i=0; i<pm->n_paths; i++ ) {
cfread_string_len(pm->paths[i].name , MAX_NAME_LEN-1, fp);
cfread_string_len(pm->paths[i].name, MAX_NAME_LEN-1, fp);
// check for reused path names... not fatal, but maybe problematic
for (j = 0; j < i; j++) {
if (!stricmp(pm->paths[i].name, pm->paths[j].name)) {
Warning(LOCATION, "Path '%s' in model %s has a name that is not unique!", pm->paths[i].name, pm->filename);
}
}
if ( pm->version >= 2002 ) {
// store the sub_model name number of the parent
cfread_string_len(pm->paths[i].parent_name , MAX_NAME_LEN-1, fp);
@@ -3073,6 +3081,8 @@ void model_set_bay_path_nums(polymodel *pm)
pm->ship_bay->arrive_flags = 0; // bitfield, set to 1 when that path number is reserved for an arrival
pm->ship_bay->depart_flags = 0; // bitfield, set to 1 when that path number is reserved for a departure
// sanity part 1
memset(pm->ship_bay->path_indexes, -1, MAX_SHIP_BAY_PATHS * sizeof(int));
// iterate through the paths that exist in the polymodel, searching for $bayN pathnames
bool too_many_paths = false;
@@ -3108,6 +3118,16 @@ void model_set_bay_path_nums(polymodel *pm)
{
Warning(LOCATION, "Model '%s' has too many bay paths - max is %d", pm->filename, MAX_SHIP_BAY_PATHS);
}
// sanity part 2
for (i = 0; i < pm->ship_bay->num_paths; i++)
{
if (pm->ship_bay->path_indexes[i] < 0)
{
Warning(LOCATION, "Model '%s' does not have a '$bay%.2d' path specified! A total of %d bay paths were counted. Either there is a gap in the path sequence, or a path has a duplicate name.", pm->filename, i + 1, pm->ship_bay->num_paths);
pm->ship_bay->path_indexes[i] = 0; // avoid crashes
}
}
}
// Get "parent" submodel for live debris submodel
+9 -2
View File
@@ -4449,9 +4449,10 @@ void multi_create_list_load_missions()
}
for (idx = 0; idx < file_count; idx++) {
int flags,max_players;
int flags, max_players;
char *filename;
uint m_respawn;
bool lcl_weirdness = false;
fname = file_list[idx];
@@ -4462,10 +4463,16 @@ void multi_create_list_load_missions()
std_gen_set_text(filename, 2);
}
// activate tstrings check
Lcl_unexpected_tstring_check = &lcl_weirdness;
flags = mission_parse_is_multi(filename, mission_name);
// deactivate tstrings check
Lcl_unexpected_tstring_check = nullptr;
// if the mission is a multiplayer mission, and we can list it, then add it to the mission list
if (flags && !mission_is_ignored(filename)) {
if (flags && !mission_is_ignored(filename) && !lcl_weirdness) {
max_players = mission_parse_get_multi_mission_info( filename );
m_respawn = The_mission.num_respawns;
+53 -53
View File
@@ -244,7 +244,7 @@ int get_line_num()
while (p < stoploc)
{
if (*p == '\0')
Assert(0);
Warning(LOCATION, "Unexpected end-of-file while looking for error line!");
if ( !incomment && (*p == COMMENT_CHAR) )
incomment = 1;
@@ -314,8 +314,6 @@ void advance_to_eoln(const char *more_terminators)
terminators[1] = 0;
if (more_terminators != NULL)
strcat_s(terminators, more_terminators);
else
terminators[1] = 0;
while (strchr(terminators, *Mp) == NULL)
Mp++;
@@ -324,7 +322,7 @@ void advance_to_eoln(const char *more_terminators)
// Advance Mp to the next white space (ignoring white space inside of " marks)
void advance_to_next_white()
{
int in_quotes = 0;
bool in_quotes = false;
while ((*Mp != EOLN) && (*Mp != '\0')) {
if (*Mp == '\"')
@@ -765,8 +763,6 @@ void copy_to_eoln(char *outstr, const char *more_terminators, const char *instr,
terminators[1] = 0;
if (more_terminators != NULL)
strcat_s(terminators, more_terminators);
else
terminators[1] = 0;
while (((ch = *instr++) != 0) && (strchr(terminators, ch) == NULL) && (count < max)) {
*outstr++ = ch;
@@ -791,8 +787,6 @@ void copy_to_eoln(SCP_string &outstr, const char *more_terminators, const char *
terminators[1] = 0;
if (more_terminators != NULL)
strcat_s(terminators, more_terminators);
else
terminators[1] = 0;
outstr = "";
while (((ch = *instr++) != 0) && (strchr(terminators, ch) == NULL)) {
@@ -802,10 +796,10 @@ void copy_to_eoln(SCP_string &outstr, const char *more_terminators, const char *
// Copy characters from instr to outstr until next white space is found, or until max
// characters have been copied (including terminator).
void copy_to_next_white(char *outstr, char *instr, int max)
void copy_to_next_white(char *outstr, const char *instr, int max)
{
int count = 0;
int in_quotes = 0;
bool in_quotes = false;
char ch;
while (((ch = *instr++)>0) && (ch != EOLN) && (ch != '\0') && (count < max)) {
@@ -831,9 +825,9 @@ void copy_to_next_white(char *outstr, char *instr, int max)
}
// Ditto for SCP_string.
void copy_to_next_white(SCP_string &outstr, char *instr)
void copy_to_next_white(SCP_string &outstr, const char *instr)
{
int in_quotes = 0;
bool in_quotes = false;
char ch;
outstr = "";
@@ -854,10 +848,10 @@ void copy_to_next_white(SCP_string &outstr, char *instr)
}
//Returns a null-terminated character string allocated with vm_malloc() with the data
char* alloc_text_until(char* instr, char* endstr)
char* alloc_text_until(const char* instr, const char* endstr)
{
Assert(instr && endstr);
char *foundstr = stristr(instr, endstr);
auto foundstr = stristr(instr, endstr);
if(foundstr == NULL)
{
@@ -888,12 +882,11 @@ char* alloc_text_until(char* instr, char* endstr)
// Copy text until a certain string is matched.
// For example, this is used to copy mission notes, scanning until $END NOTES:
// is found.
void copy_text_until(char *outstr, char *instr, const char *endstr, int max_chars)
void copy_text_until(char *outstr, const char *instr, const char *endstr, int max_chars)
{
char *foundstr;
Assert(outstr && instr && endstr);
foundstr = stristr(instr, endstr);
auto foundstr = stristr(instr, endstr);
if (foundstr == NULL) {
nprintf(("Error", "Error. Looking for [%s], but never found it.\n", endstr));
@@ -915,12 +908,11 @@ void copy_text_until(char *outstr, char *instr, const char *endstr, int max_char
}
// Ditto for SCP_string.
void copy_text_until(SCP_string &outstr, char *instr, const char *endstr)
void copy_text_until(SCP_string &outstr, const char *instr, const char *endstr)
{
char *foundstr;
Assert(instr && endstr);
foundstr = stristr(instr, endstr);
auto foundstr = stristr(instr, endstr);
if (foundstr == NULL) {
nprintf(("Error", "Error. Looking for [%s], but never found it.\n", endstr));
@@ -1367,7 +1359,7 @@ void stuff_string_line(SCP_string &outstr)
// Exactly the same as stuff string only Malloc's the buffer.
// Supports various FreeSpace primitive types. If 'len' is supplied, it will override
// the default string length if using the F_NAME case.
char *stuff_and_malloc_string(int type, char *terminators)
char *stuff_and_malloc_string(int type, const char *terminators)
{
SCP_string tmp_result;
@@ -1380,7 +1372,7 @@ char *stuff_and_malloc_string(int type, char *terminators)
return vm_strdup(tmp_result.c_str());
}
void stuff_malloc_string(char **dest, int type, char *terminators)
void stuff_malloc_string(char **dest, int type, const char *terminators)
{
Assert(dest != NULL); //wtf?
@@ -1397,53 +1389,62 @@ void stuff_malloc_string(char **dest, int type, char *terminators)
}
// After reading a multitext string, you can call this function to convert any newlines into
// spaces, so it's a one paragraph string (I.e. as in MS-Word).
//
// spaces, so it's a one paragraph string (i.e. as in MS-Word).
void compact_multitext_string(char *str)
{
size_t i;
size_t len = strlen(str);
size_t num_cr = 0;
auto p_dest = str;
auto p_src = str;
for (i=0; i<len; i++)
while (*p_src)
{
char ch = *p_src;
p_src++;
// skip CR
// convert LF to space
// copy characters backwards if any CRs previously encountered
if (str[i] == '\r')
num_cr++;
else if (str[i] == '\n')
str[i-num_cr] = ' ';
else if (num_cr > 0)
str[i-num_cr] = str[i];
if (ch != '\r')
{
if (ch == '\n')
*p_dest = ' ';
else if (p_dest != p_src)
*p_dest = *p_src;
p_dest++;
}
}
if (num_cr > 0)
str[len-num_cr] = 0;
if (p_dest != p_src)
*p_dest = 0;
}
// ditto for SCP_string
void compact_multitext_string(SCP_string &str)
{
size_t i;
size_t len = str.length();
size_t num_cr = 0;
auto p_dest = str.begin();
auto p_src = str.begin();
for (i=0; i<len; i++)
while (p_src != str.end())
{
char ch = *p_src;
p_src++;
// skip CR
// convert LF to space
// copy characters backwards if any CRs previously encountered
if (str[i] == '\r')
num_cr++;
else if (str[i] == '\n')
str[i-num_cr] = ' ';
else if (num_cr > 0)
str[i-num_cr] = str[i];
if (ch != '\r')
{
if (ch == '\n')
*p_dest = ' ';
else if (p_dest != p_src)
*p_dest = *p_src;
p_dest++;
}
}
if (num_cr > 0)
str.resize(len-num_cr);
if (p_dest != p_src)
str.erase(p_dest);
}
// Converts a character from Windows-1252 to CP437.
@@ -1987,13 +1988,12 @@ void strip_comments(char *line, bool &in_quote, bool &in_multiline_comment_a, bo
}
}
int parse_get_line(char *lineout, int max_line_len, char *start, int max_size, char *cur)
int parse_get_line(char *lineout, int max_line_len, const char *start, int max_size, const char *cur)
{
char * t = lineout;
int i, num_chars_read=0;
char c;
for ( i = 0; i < max_line_len-1; i++ ) {
do {
if ( (cur - start) >= max_size ) {
@@ -2019,7 +2019,7 @@ int parse_get_line(char *lineout, int max_line_len, char *start, int max_size, c
// Read mission text, stripping comments.
// When a comment is found, it is removed. If an entire line
// consisted of a comment, a blank line is left in the input file.
// Goober5000 - added ability to read somewhere other than Mission_text
// Goober5000 - added ability to read somewhere other than Parse_text
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
{
// copy the filename
@@ -2134,7 +2134,7 @@ void allocate_parse_text(size_t size)
Parse_text_raw = (char *) vm_malloc(sizeof(char) * size, memory::quiet_alloc);
if ( (Parse_text == nullptr) || (Parse_text_raw == nullptr) ) {
Error(LOCATION, "Unable to allocate enough memory for Mission_text! Aborting...\n");
Error(LOCATION, "Unable to allocate enough memory for Parse_text! Aborting...\n");
}
memset( Parse_text, 0, sizeof(char) * size );
@@ -2170,7 +2170,7 @@ void read_raw_file_text(const char *filename, int mode, char *raw_text)
// that if we have control over the raw_text pointer which is only the case if it's null.
auto can_reallocate = raw_text == nullptr;
if (raw_text == nullptr) {
// allocate, or reallocate, memory for Mission_text and Mission_text_raw based on size we need now
// allocate, or reallocate, memory for Parse_text and Parse_text_raw based on size we need now
allocate_parse_text((size_t) (file_len + 1));
// NOTE: this always has to be done *after* the allocate_mission_text() call!!
raw_text = Parse_text_raw;
+5 -5
View File
@@ -116,7 +116,7 @@ extern int required_string_one_of(int arg_count, ...);
// stuff
extern void copy_to_eoln(char *outstr, const char *more_terminators, const char *instr, int max);
extern void copy_text_until(char *outstr, char *instr, const char *endstr, int max_chars);
extern void copy_text_until(char *outstr, const char *instr, const char *endstr, int max_chars);
extern void stuff_string_white(char *outstr, int len = 0);
extern void stuff_string_until(char *outstr, const char *endstr, int len = 0);
extern void stuff_string(char *outstr, int type, int len, const char *terminators = NULL);
@@ -124,7 +124,7 @@ extern void stuff_string_line(char *outstr, int len);
// SCP_string stuff
extern void copy_to_eoln(SCP_string &outstr, const char *more_terminators, const char *instr);
extern void copy_text_until(SCP_string &outstr, char *instr, const char *endstr);
extern void copy_text_until(SCP_string &outstr, const char *instr, const char *endstr);
extern void stuff_string_white(SCP_string &outstr);
extern void stuff_string_until(SCP_string &outstr, const char *endstr);
extern void stuff_string(SCP_string &outstr, int type, const char *terminators = NULL);
@@ -136,8 +136,8 @@ extern char* alloc_block(const char* startstr, const char* endstr, int extra_cha
// Exactly the same as stuff string only Malloc's the buffer.
// Supports various FreeSpace primitive types. If 'len' is supplied, it will override
// the default string length if using the F_NAME case.
extern char *stuff_and_malloc_string(int type, char *terminators = NULL);
extern void stuff_malloc_string(char **dest, int type, char *terminators = NULL);
extern char *stuff_and_malloc_string(int type, const char *terminators = nullptr);
extern void stuff_malloc_string(char **dest, int type, const char *terminators = nullptr);
extern void stuff_float(float *f);
extern int stuff_float_optional(float *f, bool raw = false);
extern int stuff_int_optional(int *i, bool raw = false);
@@ -252,7 +252,7 @@ extern void reset_parse(char *text = NULL);
extern void display_parse_diagnostics();
extern void pause_parse();
extern void unpause_parse();
// stop parsing, basically just free's up the memory from Mission_text and Mission_text_raw
// stop parsing, basically just frees up the memory from Parse_text and Parse_text_raw
extern void stop_parse();
// utility
+1 -1
View File
@@ -73,7 +73,7 @@ ADE_FUNC(attacks, l_Team, "team", "Checks the IFF status of another team", "bool
{
int x, y;
ade_get_args(L, "oo", l_Team.Get(&x), l_Team.Get(&y));
if (iff_x_attacks_y(x, y) > 0)
if (iff_x_attacks_y(x, y))
return ADE_RETURN_TRUE;
return ADE_RETURN_FALSE;
+87 -50
View File
@@ -446,6 +446,7 @@ flag_def_list_new<Weapon::Info_Flags> ai_tgt_weapon_flags[] = {
{ "big ship", Weapon::Info_Flags::Big_only, true, false },
{ "child", Weapon::Info_Flags::Child, true, false },
{ "no dumbfire", Weapon::Info_Flags::No_dumbfire, true, false },
{ "no doublefire", Weapon::Info_Flags::No_doublefire, true, false },
{ "thruster", Weapon::Info_Flags::Thruster, true, false },
{ "in tech database", Weapon::Info_Flags::In_tech_database, true, false },
{ "player allowed", Weapon::Info_Flags::Player_allowed, true, false },
@@ -1611,7 +1612,7 @@ ship_info::ship_info()
sup_hull_repair_rate = 0.15f;
sup_shield_repair_rate = 0.20f;
sup_subsys_repair_rate = 0.15f;
sup_subsys_repair_rate = 0.15f; // The retail default is 0.10, but it actually used the hull rate of 0.15
vm_vec_zero(&closeup_pos);
closeup_zoom = 0.5f;
@@ -1819,7 +1820,7 @@ static void parse_ship(const char *filename, bool replace)
}
//Remove @ symbol
//these used to be used to denote weapons that would
//these used to denote weapons that would
//only be parsed in demo builds
if ( fname[0] == '@' ) {
backspace(fname);
@@ -6036,6 +6037,33 @@ const char* ship::get_display_string() {
}
}
void ship::apply_replacement_textures(SCP_vector<texture_replace> &replacements)
{
if (!replacements.empty())
{
ship_replacement_textures = (int *) vm_malloc( MAX_REPLACEMENT_TEXTURES * sizeof(int));
for (auto i = 0; i < MAX_REPLACEMENT_TEXTURES; i++)
ship_replacement_textures[i] = -1;
}
// now fill them in
for (auto tr : replacements)
{
auto pm = model_get(Ship_info[ship_info_index].model_num);
// look for textures
for (auto j = 0; j < pm->n_textures; j++)
{
texture_map *tmap = &pm->maps[j];
int tnum = tmap->FindTexture(tr.old_texture);
if(tnum > -1)
ship_replacement_textures[j * TM_NUM_TYPES + tnum] = tr.new_texture_id;
}
}
}
void ship_weapon::clear()
{
flags.reset();
@@ -6899,9 +6927,16 @@ void ship_render_cockpit(object *objp)
//Deal with the model
model_clear_instance(sip->cockpit_model_num);
uint render_flags = MR_NORMAL;
render_flags |= MR_NO_FOGGING;
if (shipp->flags[Ship::Ship_Flags::Glowmaps_disabled]) {
render_flags |= MR_NO_GLOWMAPS;
}
model_render_params render_info;
render_info.set_detail_level_lock(0);
render_info.set_flags(MR_NO_FOGGING);
render_info.set_flags(render_flags);
render_info.set_replacement_textures(Player_cockpit_textures);
model_render_immediate(&render_info, sip->cockpit_model_num, &eye_ori, &pos);
@@ -11950,6 +11985,21 @@ int ship_fire_secondary( object *obj, int allow_swarm )
goto done_secondary;
}
// Handle the optional disabling of dual fire
// dual fire/doublefire can be disabled for individual weapons, for players, or for AIs
// if any of these apply to the current weapon, unset the dual fire flag on the ship
// then proceed as normal.
// This is only handled at firing time so dualfire isn't lost when cycling through weapons
if (shipp->flags[Ship_Flags::Secondary_dual_fire] &&
( wip->wi_flags[Weapon::Info_Flags::No_doublefire] ||
( The_mission.ai_profile->flags[AI::Profile_Flags::Disable_ai_secondary_doublefire] &&
shipp->objnum != OBJ_INDEX(Player_obj) ) ||
( The_mission.ai_profile->flags[AI::Profile_Flags::Disable_player_secondary_doublefire] &&
shipp->objnum == OBJ_INDEX(Player_obj) ))
) {
shipp->flags.remove(Ship_Flags::Secondary_dual_fire);
}
int start_slot, end_slot;
if ( shipp->flags[Ship_Flags::Secondary_dual_fire] && num_slots > 1) {
@@ -13515,8 +13565,8 @@ float ship_calculate_rearm_duration( object *objp )
//
int ship_do_rearm_frame( object *objp, float frametime )
{
int i, banks_full, primary_banks_full, subsys_type, subsys_all_ok, last_ballistic_idx = -1;
float shield_str, max_shield_str = 0.0f, repair_delta, repair_allocated, max_hull_repair, max_subsys_repair;
int i, banks_full, primary_banks_full, subsys_type, last_ballistic_idx = -1;
float shield_str, max_shield_str = 0.0f, repair_delta, repair_allocated, max_hull_repair = 0, max_subsys_repair;
ship *shipp;
ship_weapon *swp;
ship_info *sip;
@@ -13538,6 +13588,7 @@ int ship_do_rearm_frame( object *objp, float frametime )
}
swp->num_primary_banks = sip->num_primary_banks;
}
// AL 12-30-97: Repair broken warp drive
if ( shipp->flags[Ship_Flags::Warp_broken] ) {
// TODO: maybe do something here like informing player warp is fixed?
@@ -13546,7 +13597,7 @@ int ship_do_rearm_frame( object *objp, float frametime )
shipp->flags.remove(Ship_Flags::Warp_broken);
}
// AL 1-16-97: Replenish countermeasures
// AL 1-16-98: Replenish countermeasures
shipp->cmeasure_count = sip->cmeasure_max;
// Do shield repair here
@@ -13567,53 +13618,36 @@ int ship_do_rearm_frame( object *objp, float frametime )
}
// Repair the ship integrity (subsystems + hull). This works by applying the repair points
// to the subsystems. Ships integrity is stored is objp->hull_strength, so that always is
// to the subsystems. Ships integrity is stored in objp->hull_strength, so that always is
// incremented by repair_allocated
repair_allocated = shipp->ship_max_hull_strength * frametime * sip->sup_hull_repair_rate;
// AL 11-24-97: remove increase to hull integrity
// Comments removed by PhReAk; Note that this is toggled on/off with a mission flag
//Figure out how much of the ship's hull we can repair
max_hull_repair = shipp->ship_max_hull_strength * (The_mission.support_ships.max_hull_repair_val * 0.01f);
//Don't "reverse-repair" the hull if it's already above the max repair threshold
if (objp->hull_strength > max_hull_repair)
// AL 11-24-97: remove increase to hull integrity
// Comments removed by PhReAk; Note that this is toggled on/off with a mission flag
if (The_mission.flags[Mission::Mission_Flags::Support_repairs_hull])
{
max_hull_repair = objp->hull_strength;
}
if(The_mission.flags[Mission::Mission_Flags::Support_repairs_hull])
{
objp->hull_strength += repair_allocated;
if ( objp->hull_strength > max_hull_repair ) {
objp->hull_strength = max_hull_repair;
}
if ( objp->hull_strength > shipp->ship_max_hull_strength )
//Figure out how much of the ship's hull we can repair
//Don't "reverse-repair" the hull if it's already above the max repair threshold
max_hull_repair = shipp->ship_max_hull_strength * (The_mission.support_ships.max_hull_repair_val * 0.01f);
if (objp->hull_strength < max_hull_repair)
{
objp->hull_strength = shipp->ship_max_hull_strength;
repair_allocated -= ( shipp->ship_max_hull_strength - objp->hull_strength);
objp->hull_strength += shipp->ship_max_hull_strength * frametime * sip->sup_hull_repair_rate;
if (objp->hull_strength > max_hull_repair)
objp->hull_strength = max_hull_repair;
}
}
// figure out repairs for subsystems
if(sip->sup_subsys_repair_rate == 0.0f)
repair_allocated = 0.0f;
else if(sip->sup_hull_repair_rate == 0.0f)
repair_allocated = shipp->ship_max_hull_strength * frametime * sip->sup_subsys_repair_rate;
else if(!(sip->sup_hull_repair_rate == sip->sup_subsys_repair_rate))
repair_allocated = repair_allocated * sip->sup_subsys_repair_rate / sip->sup_hull_repair_rate;
repair_allocated = shipp->ship_max_hull_strength * frametime * sip->sup_subsys_repair_rate;
// check the subsystems of the ship.
subsys_all_ok = 1;
bool subsys_all_ok = true;
ssp = GET_FIRST(&shipp->subsys_list);
while ( ssp != END_OF_LIST( &shipp->subsys_list ) ) {
//Figure out how much we *can* repair the current subsystem -C
max_subsys_repair = ssp->max_hits * (The_mission.support_ships.max_subsys_repair_val * 0.01f);
if ( ssp->current_hits < max_subsys_repair && repair_allocated > 0 ) {
subsys_all_ok = 0;
subsys_all_ok = false;
subsys_type = ssp->system_info->type;
if ( objp == Player_obj ) {
@@ -13779,7 +13813,8 @@ int ship_do_rearm_frame( object *objp, float frametime )
if ((aip->rearm_first_ballistic_primary == TRUE) && (i == last_ballistic_idx))
{
if (primary_banks_full != swp->num_primary_banks) {
if (primary_banks_full != swp->num_primary_banks)
{
// Goober5000
gamesnd_id sound_index;
if (gamesnd_game_sound_valid(GameSounds::BALLISTIC_START_LOAD))
@@ -13805,23 +13840,24 @@ int ship_do_rearm_frame( object *objp, float frametime )
aip->rearm_first_ballistic_primary = TRUE;
}
int shields_full = 0;
int shields_full = false;
if ( (objp->flags[Object::Object_Flags::No_shields]) ) {
shields_full = 1;
shields_full = true;
} else {
if ( shield_get_strength(objp) >= max_shield_str )
shields_full = 1;
shields_full = true;
if (sip->sup_shield_repair_rate == 0.0f)
shields_full = 1;
shields_full = true;
}
int hull_ok = 0;
if(objp->hull_strength >= max_hull_repair)
hull_ok = 1;
if(sip->sup_hull_repair_rate == 0.0f) {
subsys_all_ok = 1;
hull_ok = 1;
bool hull_ok = false;
if (!(The_mission.flags[Mission::Mission_Flags::Support_repairs_hull])) {
hull_ok = true;
} else {
if (objp->hull_strength >= max_hull_repair)
hull_ok = true;
if (sip->sup_hull_repair_rate == 0.0f)
hull_ok = true;
}
// return 1 if at end of subsystem list, hull damage at 0, and shields full and all secondary banks full.
@@ -13846,7 +13882,8 @@ int ship_do_rearm_frame( object *objp, float frametime )
}
}
if (objp == Player_obj) Player_rearm_eta -= frametime;
if (objp == Player_obj)
Player_rearm_eta -= frametime;
return 0;
}
+2
View File
@@ -727,6 +727,8 @@ public:
bool has_display_name();
const char* get_display_string();
void apply_replacement_textures(SCP_vector<texture_replace> &replacements);
};
struct ai_target_priority {
+4
View File
@@ -1582,6 +1582,10 @@ void shipfx_queue_render_ship_halves_and_debris(model_draw_list *scene, clip_shi
render_flags |= MR_NO_TEXTURING | MR_NO_LIGHTING;
}
if (shipp->flags[Ship::Ship_Flags::Glowmaps_disabled]) {
render_flags |= MR_NO_GLOWMAPS;
}
for (int i = 0; i < pm->num_debris_objects; i++ ) {
// draw DEBRIS_FREE in test only
if (half_ship->draw_debris[i] == DEBRIS_DRAW) {
+14
View File
@@ -38,6 +38,7 @@
#include "object/objectshield.h"
#include "object/objectsnd.h"
#include "parse/parselo.h"
#include "scripting/hook_api.h"
#include "scripting/scripting.h"
#include "scripting/api/objs/subsystem.h"
#include "playerman/player.h"
@@ -72,6 +73,12 @@ vec3d Original_vec_to_deader;
static bool global_damage = false;
const std::shared_ptr<scripting::Hook> OnPainFlashHook = scripting::Hook::Factory(
"On Pain Flash", "Called when a pain flash is displayed.",
{
{"Pain_Type", "number", "The type of pain flash displayed: shield = 0 and hull = 1."},
});
//WMC - Camera rough draft stuff
/*
camid dead_get_camera()
@@ -2637,6 +2644,7 @@ void ship_hit_pain(float damage, int quadrant)
if (!(Player_obj->flags[Object::Object_Flags::Invulnerable]))
{
int pain_type;
if (Shield_pain_flash_factor != 0.0f && quadrant >= 0)
{
float effect = (Shield_pain_flash_factor * Player_obj->shield_quadrant[quadrant] * Player_obj->n_quadrants) / shield_get_max_strength(Player_obj);
@@ -2645,9 +2653,15 @@ void ship_hit_pain(float damage, int quadrant)
effect -= Shield_pain_flash_factor;
game_flash((sip->shield_color[0] * effect) / 255.0f, (sip->shield_color[1] * effect) / 255.0f, (sip->shield_color[2] * effect) / 255.0f);
pain_type = 0;
}
else
{
game_flash(damage * Generic_pain_flash_factor / 15.0f, -damage * Generic_pain_flash_factor / 30.0f, -damage * Generic_pain_flash_factor / 30.0f);
pain_type = 1;
}
// add scripting hook for 'On Pain Flash' --wookieejedi
OnPainFlashHook->run(scripting::hook_param_list(scripting::hook_param("Pain_Type", 'i', pain_type)));
}
// kill any active popups when you get hit.
+1
View File
@@ -23,6 +23,7 @@ namespace Weapon {
Bomb, // Bomb-type missile, can be targeted
Huge, // Huge damage (generally 500+), probably only fired at huge ships.
No_dumbfire, // Missile cannot be fired dumbfire (ie requires aspect lock)
No_doublefire, // Disables linked firing for secondaries - EatThePath
Thruster, // Has thruster cone and/or glow
In_tech_database,
Player_allowed, // allowed to be on starting wing ships/in weaponry pool
+2 -1
View File
@@ -115,6 +115,7 @@ flag_def_list_new<Weapon::Info_Flags> Weapon_Info_Flags[] = {
{ "child", Weapon::Info_Flags::Child, true, false },
{ "bomb", Weapon::Info_Flags::Bomb, true, false },
{ "no dumbfire", Weapon::Info_Flags::No_dumbfire, true, false },
{ "no doublefire", Weapon::Info_Flags::No_doublefire, true, false },
{ "in tech database", Weapon::Info_Flags::In_tech_database, true, false },
{ "player allowed", Weapon::Info_Flags::Player_allowed, true, false },
{ "particle spew", Weapon::Info_Flags::Particle_spew, true, false },
@@ -808,7 +809,7 @@ int parse_weapon(int subtype, bool replace, const char *filename)
}
//Remove @ symbol
//these used to be used to denote weapons that would
//these used to denote weapons that would
//only be parsed in demo builds
if ( fname[0] == '@' ) {
backspace(fname);
+3 -6
View File
@@ -231,9 +231,8 @@ BOOL CFREDApp::InitInstance() {
Lighting_on = GetProfileInt("Preferences", "Lighting On", Lighting_on);
// Goober5000
Format_fs2_open = GetProfileInt("Preferences", "FS2 open format", Format_fs2_open);
Format_fs2_retail = GetProfileInt("Preferences", "FS2 retail format", Format_fs2_retail);
Format_fs1_retail = GetProfileInt("Preferences", "FS1 retail format", Format_fs1_retail);
Mission_save_format = GetProfileInt("Preferences", "FS2 open format", FSO_FORMAT_STANDARD);
Mission_save_format = GetProfileInt("Preferences", "Mission save format", Mission_save_format);
read_window("Main window", &Main_wnd_data);
read_window("Ship window", &Ship_wnd_data);
@@ -493,9 +492,7 @@ void CFREDApp::write_ini_file(int degree) {
WriteProfileInt("Preferences", "Lighting On", Lighting_on);
// Goober5000
WriteProfileInt("Preferences", "FS2 open format", Format_fs2_open);
WriteProfileInt("Preferences", "FS2 retail format", Format_fs2_retail);
WriteProfileInt("Preferences", "FS1 retail format", Format_fs1_retail);
WriteProfileInt("Preferences", "Mission save format", Mission_save_format);
if (!degree) {
record_window_data(&Waypoint_wnd_data, &Waypoint_editor_dialog);
+9 -19
View File
@@ -107,9 +107,7 @@ Marking_box marking_box;
object_orient_pos rotation_backup[MAX_OBJECTS];
// Goober5000 (currently, FS1 retail not implemented)
int Format_fs2_open = FSO_FORMAT_STANDARD;
int Format_fs2_retail = 0;
int Format_fs1_retail = 0;
int Mission_save_format = FSO_FORMAT_STANDARD;
// used by error checker, but needed in more than just one function.
char *names[MAX_OBJECTS], flags[MAX_OBJECTS];
@@ -4523,9 +4521,7 @@ void CFREDView::OnDumpStats()
void CFREDView::OnFormatFs2Open()
{
Format_fs2_open = FSO_FORMAT_STANDARD;
Format_fs2_retail = 0;
Format_fs1_retail = 0;
Mission_save_format = FSO_FORMAT_STANDARD;
theApp.write_ini_file();
Update_window = 1;
@@ -4533,14 +4529,12 @@ void CFREDView::OnFormatFs2Open()
void CFREDView::OnUpdateFormatFs2Open(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(Format_fs2_open == FSO_FORMAT_STANDARD);
pCmdUI->SetCheck(Mission_save_format == FSO_FORMAT_STANDARD);
}
void CFREDView::OnFormatFs2OpenComp()
{
Format_fs2_open = FSO_FORMAT_COMPATIBILITY_MODE;
Format_fs2_retail = 0;
Format_fs1_retail = 0;
Mission_save_format = FSO_FORMAT_COMPATIBILITY_MODE;
theApp.write_ini_file();
Update_window = 1;
@@ -4548,14 +4542,12 @@ void CFREDView::OnFormatFs2OpenComp()
void CFREDView::OnUpdateFormatFs2OpenComp(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(Format_fs2_open == FSO_FORMAT_COMPATIBILITY_MODE);
pCmdUI->SetCheck(Mission_save_format == FSO_FORMAT_COMPATIBILITY_MODE);
}
void CFREDView::OnFormatFs2Retail()
{
Format_fs2_open = FSO_FORMAT_RETAIL;
Format_fs2_retail = 1;
Format_fs1_retail = 0;
Mission_save_format = FSO_FORMAT_RETAIL;
theApp.write_ini_file();
Update_window = 1;
@@ -4563,14 +4555,12 @@ void CFREDView::OnFormatFs2Retail()
void CFREDView::OnUpdateFormatFs2Retail(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(Format_fs2_retail);
pCmdUI->SetCheck(Mission_save_format == FSO_FORMAT_RETAIL);
}
void CFREDView::OnFormatFs1Retail()
{
Format_fs2_open = FSO_FORMAT_RETAIL;
Format_fs2_retail = 0;
Format_fs1_retail = 1;
Mission_save_format = FSO_FORMAT_RETAIL;
theApp.write_ini_file();
Update_window = 1;
@@ -4578,7 +4568,7 @@ void CFREDView::OnFormatFs1Retail()
void CFREDView::OnUpdateFormatFs1Retail(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(Format_fs1_retail);
pCmdUI->SetCheck(Mission_save_format == FSO_FORMAT_RETAIL);
}
void CFREDView::OnEditorsSetGlobalShipFlags()
+1 -5
View File
@@ -364,11 +364,7 @@ enum FSO_FORMAT
FSO_FORMAT_STANDARD = 1,
FSO_FORMAT_COMPATIBILITY_MODE = 2
};
// Goober5000 (currently, FS1 retail not implemented)
extern int Format_fs2_open;
extern int Format_fs2_retail;
extern int Format_fs1_retail;
extern int Mission_save_format;
extern CFREDView *Fred_view_wnd;
+187 -122
View File
@@ -51,7 +51,8 @@
#include <freespace.h>
int CFred_mission_save::autosave_mission_file(char *pathname) {
int CFred_mission_save::autosave_mission_file(char *pathname)
{
char backup_name[256], name2[256];
int i;
@@ -73,7 +74,8 @@ int CFred_mission_save::autosave_mission_file(char *pathname) {
return err;
}
void CFred_mission_save::bypass_comment(const char *comment, const char *end) {
void CFred_mission_save::bypass_comment(const char *comment, const char *end)
{
char *ch = strstr(raw_ptr, comment);
if (ch != NULL) {
if (end != NULL) {
@@ -96,20 +98,23 @@ void CFred_mission_save::bypass_comment(const char *comment, const char *end) {
}
}
void CFred_mission_save::convert_special_tags_to_retail(char *text, int max_len) {
void CFred_mission_save::convert_special_tags_to_retail(char *text, int max_len)
{
replace_all(text, "$quote", "''", max_len);
replace_all(text, "$semicolon", ",", max_len);
}
void CFred_mission_save::convert_special_tags_to_retail(SCP_string &text) {
void CFred_mission_save::convert_special_tags_to_retail(SCP_string &text)
{
replace_all(text, "$quote", "''");
replace_all(text, "$semicolon", ",");
}
void CFred_mission_save::convert_special_tags_to_retail() {
void CFred_mission_save::convert_special_tags_to_retail()
{
int i, team, stage;
if (Format_fs2_open != FSO_FORMAT_RETAIL)
if (Mission_save_format != FSO_FORMAT_RETAIL)
return;
for (team = 0; team < Num_teams; team++) {
@@ -134,7 +139,8 @@ void CFred_mission_save::convert_special_tags_to_retail() {
}
}
int CFred_mission_save::fout(char *format, ...) {
int CFred_mission_save::fout(char *format, ...)
{
SCP_string str;
va_list args;
@@ -150,7 +156,8 @@ int CFred_mission_save::fout(char *format, ...) {
return 0;
}
int CFred_mission_save::fout_ext(char *pre_str, char *format, ...) {
int CFred_mission_save::fout_ext(char *pre_str, char *format, ...)
{
SCP_string str_scp;
SCP_string str_out_scp;
va_list args;
@@ -252,7 +259,8 @@ int CFred_mission_save::fout_ext(char *pre_str, char *format, ...) {
return 0;
}
int CFred_mission_save::fout_version(char *format, ...) {
int CFred_mission_save::fout_version(char *format, ...)
{
SCP_string str_scp;
char *ch = NULL;
va_list args;
@@ -261,9 +269,14 @@ int CFred_mission_save::fout_version(char *format, ...) {
return err;
}
// if we're saving in retail format, we can completely skip this
if (Mission_save_format == FSO_FORMAT_RETAIL) {
return 0;
}
// output the version first thing, but skip the special case where we use
// fout_version() for multiline value strings (typically indicated by an initial space)
if ((Format_fs2_open == FSO_FORMAT_COMPATIBILITY_MODE) && (*format != ' ') && !fso_ver_comment.empty()) {
if ((Mission_save_format == FSO_FORMAT_COMPATIBILITY_MODE) && (*format != ' ') && !fso_ver_comment.empty()) {
while (*format == '\n') {
str_scp.append(1, *format);
format++;
@@ -284,7 +297,7 @@ int CFred_mission_save::fout_version(char *format, ...) {
char *str_c = vm_strdup(str_scp.c_str());
// this could be a multi-line string, so we've got to handle it all properly
if ((Format_fs2_open == FSO_FORMAT_COMPATIBILITY_MODE) && !fso_ver_comment.empty()) {
if ((Mission_save_format == FSO_FORMAT_COMPATIBILITY_MODE) && !fso_ver_comment.empty()) {
bool first_line = true;
char *str_p = str_c;
@@ -341,7 +354,8 @@ int CFred_mission_save::fout_version(char *format, ...) {
return 0;
}
void CFred_mission_save::parse_comments(int newlines) {
void CFred_mission_save::parse_comments(int newlines)
{
char *comment_start = NULL;
int state = 0, same_line = 0, first_comment = 1, tab = 0, flag = 0;
bool version_added = false;
@@ -501,7 +515,8 @@ void CFred_mission_save::parse_comments(int newlines) {
return;
}
void CFred_mission_save::save_ai_goals(ai_goal *goalp, int ship) {
void CFred_mission_save::save_ai_goals(ai_goal *goalp, int ship)
{
char *str = NULL, buf[80];
int i, valid, flag = 1;
@@ -654,7 +669,8 @@ void CFred_mission_save::save_ai_goals(ai_goal *goalp, int ship) {
fso_comment_pop(true);
}
int CFred_mission_save::save_asteroid_fields() {
int CFred_mission_save::save_asteroid_fields()
{
int i;
fred_parse_flag = 0;
@@ -748,7 +764,8 @@ int CFred_mission_save::save_asteroid_fields() {
return err;
}
int CFred_mission_save::save_bitmaps() {
int CFred_mission_save::save_bitmaps()
{
int i;
uint j;
@@ -894,7 +911,8 @@ int CFred_mission_save::save_bitmaps() {
return err;
}
int CFred_mission_save::save_briefing() {
int CFred_mission_save::save_briefing()
{
int i, j, k, nb;
SCP_string sexp_out;
brief_stage *bs;
@@ -1027,13 +1045,13 @@ int CFred_mission_save::save_briefing() {
parse_comments();
fout(" %d", (bi->flags & BI_HIGHLIGHT) ? 1 : 0);
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
required_string_fred("$mirror:");
parse_comments();
fout(" %d", (bi->flags & BI_MIRROR_ICON) ? 1 : 0);
}
if ((Format_fs2_open != FSO_FORMAT_RETAIL) && (bi->flags & BI_USE_WING_ICON)) {
if ((Mission_save_format != FSO_FORMAT_RETAIL) && (bi->flags & BI_USE_WING_ICON)) {
required_string_fred("$use wing icon:");
parse_comments();
fout(" %d", (bi->flags & BI_USE_WING_ICON) ? 1 : 0);
@@ -1070,7 +1088,8 @@ int CFred_mission_save::save_briefing() {
return err;
}
int CFred_mission_save::save_campaign_file(char *pathname) {
int CFred_mission_save::save_campaign_file(char *pathname)
{
int i, j, m, flag;
Campaign_tree_formp->save_tree(); // flush all changes so they get saved.
@@ -1109,7 +1128,7 @@ int CFred_mission_save::save_campaign_file(char *pathname) {
}
// campaign flags - Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
optional_string_fred("$Flags:");
parse_comments();
fout(" %d\n", Campaign.flags);
@@ -1153,7 +1172,7 @@ int CFred_mission_save::save_campaign_file(char *pathname) {
parse_comments();
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
// don't save Bastion flag
fout(" %d", Campaign.missions[m].flags & ~CMISSION_FLAG_BASTION);
@@ -1201,7 +1220,7 @@ int CFred_mission_save::save_campaign_file(char *pathname) {
//save_campaign_sexp(Links[j].sexp, Campaign.missions[Links[j].to].name);
if (Links[j].is_mission_loop) {
mission_loop = true;
} else if (Links[j].is_mission_fork) {
} else if (Links[j].is_mission_fork && (Mission_save_format != FSO_FORMAT_RETAIL)) {
mission_fork = true;
} else {
save_campaign_sexp(Links[j].sexp, Links[j].to);
@@ -1312,7 +1331,8 @@ int CFred_mission_save::save_campaign_file(char *pathname) {
return err;
}
void CFred_mission_save::save_campaign_sexp(int node, int link_num) {
void CFred_mission_save::save_campaign_sexp(int node, int link_num)
{
SCP_string sexp_out;
Assert(node >= 0);
@@ -1332,7 +1352,8 @@ void CFred_mission_save::save_campaign_sexp(int node, int link_num) {
}
}
int CFred_mission_save::save_cmd_brief() {
int CFred_mission_save::save_cmd_brief()
{
int stage;
stage = 0;
@@ -1370,7 +1391,8 @@ int CFred_mission_save::save_cmd_brief() {
return err;
}
int CFred_mission_save::save_cmd_briefs() {
int CFred_mission_save::save_cmd_briefs()
{
int i;
for (i = 0; i < Num_teams; i++) {
@@ -1381,7 +1403,8 @@ int CFred_mission_save::save_cmd_briefs() {
return err;
}
void CFred_mission_save::fso_comment_push(char *ver) {
void CFred_mission_save::fso_comment_push(char *ver)
{
if (fso_ver_comment.empty()) {
fso_ver_comment.push_back(SCP_string(ver));
return;
@@ -1414,7 +1437,8 @@ void CFred_mission_save::fso_comment_push(char *ver) {
}
}
void CFred_mission_save::fso_comment_pop(bool pop_all) {
void CFred_mission_save::fso_comment_pop(bool pop_all)
{
if (fso_ver_comment.empty()) {
return;
}
@@ -1427,7 +1451,8 @@ void CFred_mission_save::fso_comment_pop(bool pop_all) {
fso_ver_comment.pop_back();
}
int CFred_mission_save::save_common_object_data(object *objp, ship *shipp) {
int CFred_mission_save::save_common_object_data(object *objp, ship *shipp)
{
int j, z;
ship_subsys *ptr = NULL;
ship_info *sip = NULL;
@@ -1446,7 +1471,7 @@ int CFred_mission_save::save_common_object_data(object *objp, ship *shipp) {
}
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL && (shipp->special_hitpoints)) {
if (Mission_save_format != FSO_FORMAT_RETAIL && (shipp->special_hitpoints > 0)) {
temp_max_hull_strength = (float) shipp->special_hitpoints;
} else {
temp_max_hull_strength = sip->max_hull_strength;
@@ -1602,8 +1627,9 @@ int CFred_mission_save::save_common_object_data(object *objp, ship *shipp) {
return err;
}
void CFred_mission_save::save_custom_bitmap(const char *expected_string_640, const char *expected_string_1024, const char *string_field_640, const char *string_field_1024, int blank_lines) {
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
void CFred_mission_save::save_custom_bitmap(const char *expected_string_640, const char *expected_string_1024, const char *string_field_640, const char *string_field_1024, int blank_lines)
{
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if ((*string_field_640 != '\0') || (*string_field_1024 != '\0')) {
while (blank_lines-- > 0)
fout("\n");
@@ -1619,13 +1645,14 @@ void CFred_mission_save::save_custom_bitmap(const char *expected_string_640, con
}
}
int CFred_mission_save::save_cutscenes() {
int CFred_mission_save::save_cutscenes()
{
char type[NAME_LENGTH];
SCP_string sexp_out;
// Let's just assume it has them for now -
if (!(The_mission.cutscenes.empty())) {
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (optional_string_fred("#Cutscenes")) {
parse_comments(2);
} else {
@@ -1675,7 +1702,7 @@ int CFred_mission_save::save_cutscenes() {
required_string_fred("#end");
parse_comments();
} else {
MessageBox(NULL, "Warning: This mission contains cutscene data, but you are saving in the retail mission format. This information will be lost", "Incompatibility with retail mission format", MB_OK);
MessageBox(nullptr, "Warning: This mission contains cutscene data, but you are saving in the retail mission format. This information will be lost.", "Incompatibility with retail mission format", MB_OK);
}
}
@@ -1683,7 +1710,8 @@ int CFred_mission_save::save_cutscenes() {
return err;
}
int CFred_mission_save::save_debriefing() {
int CFred_mission_save::save_debriefing()
{
int j, i;
SCP_string sexp_out;
@@ -1739,7 +1767,8 @@ int CFred_mission_save::save_debriefing() {
return err;
}
int CFred_mission_save::save_events() {
int CFred_mission_save::save_events()
{
SCP_string sexp_out;
int i, j, add_flag;
@@ -1778,7 +1807,7 @@ int CFred_mission_save::save_events() {
fout(" %d", Mission_events[i].repeat_count);
}
if (Format_fs2_open != FSO_FORMAT_RETAIL && Mission_events[i].trigger_count != 1) {
if (Mission_save_format != FSO_FORMAT_RETAIL && Mission_events[i].trigger_count != 1) {
fso_comment_push(";;FSO 3.6.11;;");
if (optional_string_fred("+Trigger Count:", "$Formula:")) {
parse_comments();
@@ -1851,7 +1880,7 @@ int CFred_mission_save::save_events() {
// save flags, if any
// (the transient flags are not used in FRED, so if the flags field is nonzero they will all be meaningful flags from the flag list)
if (Format_fs2_open != FSO_FORMAT_RETAIL && Mission_events[i].flags != 0) {
if (Mission_save_format != FSO_FORMAT_RETAIL && Mission_events[i].flags != 0) {
fso_comment_push(";;FSO 20.0.0;;");
if (optional_string_fred("+Event Flags: (", "$Formula:")) {
parse_comments();
@@ -1868,7 +1897,7 @@ int CFred_mission_save::save_events() {
fout(" )");
}
if (Format_fs2_open != FSO_FORMAT_RETAIL && Mission_events[i].mission_log_flags != 0) {
if (Mission_save_format != FSO_FORMAT_RETAIL && Mission_events[i].mission_log_flags != 0) {
fso_comment_push(";;FSO 3.6.11;;");
if (optional_string_fred("+Event Log Flags: (", "$Formula:")) {
parse_comments();
@@ -1894,9 +1923,10 @@ int CFred_mission_save::save_events() {
return err;
}
int CFred_mission_save::save_fiction() {
int CFred_mission_save::save_fiction()
{
if (mission_has_fiction()) {
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (optional_string_fred("#Fiction Viewer"))
parse_comments(2);
else
@@ -1960,7 +1990,7 @@ int CFred_mission_save::save_fiction() {
optional_string_fred("$Formula:");
}
} else {
MessageBox(NULL, "Warning: This mission contains fiction viewer data, but you are saving in the retail mission format.", "Incompatibility with retail mission format", MB_OK);
MessageBox(nullptr, "Warning: This mission contains fiction viewer data, but you are saving in the retail mission format.", "Incompatibility with retail mission format", MB_OK);
}
}
@@ -1969,7 +1999,8 @@ int CFred_mission_save::save_fiction() {
return err;
}
int CFred_mission_save::save_goals() {
int CFred_mission_save::save_goals()
{
SCP_string sexp_out;
int i;
@@ -2048,14 +2079,16 @@ int CFred_mission_save::save_goals() {
return err;
}
int CFred_mission_save::save_matrix(matrix &m) {
int CFred_mission_save::save_matrix(matrix &m)
{
fout("\n\t%f, %f, %f,\n", m.vec.rvec.xyz.x, m.vec.rvec.xyz.y, m.vec.rvec.xyz.z);
fout("\t%f, %f, %f,\n", m.vec.uvec.xyz.x, m.vec.uvec.xyz.y, m.vec.uvec.xyz.z);
fout("\t%f, %f, %f", m.vec.fvec.xyz.x, m.vec.fvec.xyz.y, m.vec.fvec.xyz.z);
return 0;
}
int CFred_mission_save::save_messages() {
int CFred_mission_save::save_messages()
{
int i;
fred_parse_flag = 0;
@@ -2064,7 +2097,7 @@ int CFred_mission_save::save_messages() {
fout("\t\t;! %d total\n", Num_messages - Num_builtin_messages);
// Goober5000 - special Command info
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (stricmp(The_mission.command_sender, DEFAULT_COMMAND))
fout("\n$Command Sender: %s", The_mission.command_sender);
@@ -2130,7 +2163,8 @@ int CFred_mission_save::save_messages() {
return err;
}
int CFred_mission_save::save_mission_file(char *pathname) {
int CFred_mission_save::save_mission_file(char *pathname)
{
char backup_name[256], savepath[MAX_PATH_LEN], *p;
strcpy_s(savepath, "");
@@ -2160,7 +2194,8 @@ int CFred_mission_save::save_mission_file(char *pathname) {
return err;
}
int CFred_mission_save::save_mission_info() {
int CFred_mission_save::save_mission_info()
{
required_string_fred("#Mission Info");
parse_comments(0);
@@ -2235,7 +2270,7 @@ int CFred_mission_save::save_mission_info() {
}
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
// write out the nebula clipping multipliers
fout("\n+Fog Near Mult: %f\n", Neb2_fog_near_mult);
fout("\n+Fog Far Mult: %f\n", Neb2_fog_far_mult);
@@ -2261,7 +2296,7 @@ int CFred_mission_save::save_mission_info() {
fout(" %d", The_mission.num_respawns);
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
fso_comment_push(";;FSO 3.6.11;;");
if (optional_string_fred("+Max Respawn Time:"))
parse_comments(2);
@@ -2276,7 +2311,7 @@ int CFred_mission_save::save_mission_info() {
}
}
if (Format_fs2_open == FSO_FORMAT_RETAIL) {
if (Mission_save_format == FSO_FORMAT_RETAIL) {
if (optional_string_fred("+Red Alert:"))
parse_comments(2);
else
@@ -2285,7 +2320,7 @@ int CFred_mission_save::save_mission_info() {
fout(" %d", (The_mission.flags[Mission::Mission_Flags::Red_alert]) ? 1 : 0);
}
if (Format_fs2_open == FSO_FORMAT_RETAIL) //-V581
if (Mission_save_format == FSO_FORMAT_RETAIL) //-V581
{
if (optional_string_fred("+Scramble:"))
parse_comments(2);
@@ -2304,7 +2339,7 @@ int CFred_mission_save::save_mission_info() {
fout(" %d", (The_mission.support_ships.max_support_ships == 0) ? 1 : 0);
// here be WMCoolmon's hull and subsys repair stuff
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (optional_string_fred("+Hull Repair Ceiling:")) {
parse_comments(1);
} else {
@@ -2365,7 +2400,7 @@ int CFred_mission_save::save_mission_info() {
}
// Goober5000 - special wing info
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
int i;
fout("\n");
@@ -2499,7 +2534,8 @@ int CFred_mission_save::save_mission_info() {
return err;
}
void CFred_mission_save::save_mission_internal(const char *pathname) {
void CFred_mission_save::save_mission_internal(const char *pathname)
{
CTime t;
t = CTime::GetCurrentTime();
@@ -2570,7 +2606,8 @@ void CFred_mission_save::save_mission_internal(const char *pathname) {
mprintf(("Mission saving error code #%d\n", err));
}
int CFred_mission_save::save_music() {
int CFred_mission_save::save_music()
{
required_string_fred("#Music");
parse_comments(2);
@@ -2628,7 +2665,7 @@ int CFred_mission_save::save_music() {
}
fout(" %s", Mission_music[SCORE_DEBRIEF_SUCCESS] < 0 ? "None" : Spooled_music[Mission_music[SCORE_DEBRIEF_SUCCESS]].name);
}
if (Mission_music[SCORE_DEBRIEF_AVERAGE] != event_music_get_spooled_music_index("Average")) {
if (Mission_save_format != FSO_FORMAT_RETAIL && Mission_music[SCORE_DEBRIEF_AVERAGE] != event_music_get_spooled_music_index("Average")) {
if (optional_string_fred("$Debriefing Average Music:")) {
parse_comments(1);
} else {
@@ -2666,6 +2703,9 @@ int CFred_mission_save::save_music() {
int CFred_mission_save::save_warp_params(WarpDirection direction, ship *shipp)
{
if (Mission_save_format == FSO_FORMAT_RETAIL)
return err;
// for writing to file; c.f. parse_warp_params
const char *prefix = (direction == WarpDirection::WARP_IN) ? "$Warpin" : "$Warpout";
@@ -2760,7 +2800,8 @@ int CFred_mission_save::save_warp_params(WarpDirection direction, ship *shipp)
return err;
}
int CFred_mission_save::save_objects() {
int CFred_mission_save::save_objects()
{
SCP_string sexp_out;
int i, z;
ai_info *aip;
@@ -2791,7 +2832,7 @@ int CFred_mission_save::save_objects() {
fout(" %s\t\t;! Object #%d\n", shipp->ship_name, i);
// Display name
if (Format_fs2_open != FSO_FORMAT_RETAIL && shipp->has_display_name()) {
if (Mission_save_format != FSO_FORMAT_RETAIL && shipp->has_display_name()) {
// The display name is only written if there was one at the start to avoid introducing inconsistencies
fout("\n$Display name:");
fout_ext(" ", "%s", shipp->display_name.c_str());
@@ -2803,7 +2844,7 @@ int CFred_mission_save::save_objects() {
fout(" %s", Ship_info[shipp->ship_info_index].name);
//alt classes stuff
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
for (SCP_vector<alt_class>::iterator ii = shipp->s_alt_classes.begin(); ii != shipp->s_alt_classes.end(); ++ii) {
// is this a variable?
if (ii->variable_index != -1) {
@@ -2825,7 +2866,7 @@ int CFred_mission_save::save_objects() {
}
// optional callsign
if (strlen(Fred_callsigns[i])) {
if (Mission_save_format != FSO_FORMAT_RETAIL && strlen(Fred_callsigns[i])) {
fout("\n$Callsign: %s\n", Fred_callsigns[i]);
}
@@ -2833,7 +2874,7 @@ int CFred_mission_save::save_objects() {
parse_comments();
fout(" %s", Iff_info[shipp->team].iff_name);
if (Ship_info[shipp->ship_info_index].uses_team_colors) {
if (Mission_save_format != FSO_FORMAT_RETAIL && Ship_info[shipp->ship_info_index].uses_team_colors) {
required_string_fred("$Team Color Setting:");
parse_comments();
fout(" %s", shipp->team_name.c_str());
@@ -2847,7 +2888,7 @@ int CFred_mission_save::save_objects() {
parse_comments();
save_matrix(Objects[shipp->objnum].orient);
if (Format_fs2_retail) {
if (Mission_save_format == FSO_FORMAT_RETAIL) {
required_string_fred("$IFF:");
parse_comments();
fout(" %s", "IFF 1");
@@ -2904,7 +2945,7 @@ int CFred_mission_save::save_objects() {
if (z & SPECIAL_ARRIVAL_ANCHOR_FLAG) {
// get name
char tmp[NAME_LENGTH + 15];
stuff_special_arrival_anchor_name(tmp, z, Format_fs2_retail);
stuff_special_arrival_anchor_name(tmp, z, Mission_save_format == FSO_FORMAT_RETAIL ? 1 : 0);
// save it
fout(" %s", tmp);
@@ -2916,7 +2957,7 @@ int CFred_mission_save::save_objects() {
}
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if ((shipp->arrival_location == ARRIVE_FROM_DOCK_BAY) && (shipp->arrival_path_mask > 0)) {
int anchor_shipnum;
polymodel *pm;
@@ -2970,7 +3011,7 @@ int CFred_mission_save::save_objects() {
}
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if ((shipp->departure_location == DEPART_AT_DOCK_BAY) && (shipp->departure_path_mask > 0)) {
int anchor_shipnum;
polymodel *pm;
@@ -3071,12 +3112,12 @@ int CFred_mission_save::save_objects() {
if (shipp->flags[Ship::Ship_Flags::Dont_collide_invis])
fout(" \"don't-collide-invisible\"");
//for compatibility reasons ship locked or weapons locked are saved as both locked in retail mode
if ((Format_fs2_open == FSO_FORMAT_RETAIL) && ((shipp->flags[Ship::Ship_Flags::Ship_locked]) || (shipp->flags[Ship::Ship_Flags::Weapons_locked])))
if ((Mission_save_format == FSO_FORMAT_RETAIL) && ((shipp->flags[Ship::Ship_Flags::Ship_locked]) || (shipp->flags[Ship::Ship_Flags::Weapons_locked])))
fout(" \"locked\"");
fout(" )");
// flags2 added by Goober5000 --------------------------------
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (optional_string_fred("+Flags2:", "$Name:")) {
parse_comments();
fout(" (");
@@ -3150,7 +3191,7 @@ int CFred_mission_save::save_objects() {
}
// special explosions
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (shipp->use_special_explosion) {
fso_comment_push(";;FSO 3.6.13;;");
if (optional_string_fred("$Special Explosion:", "$Name:")) {
@@ -3240,7 +3281,7 @@ int CFred_mission_save::save_objects() {
}
// Goober5000 ------------------------------------------------
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (shipp->special_hitpoints) {
fso_comment_push(";;FSO 3.6.13;;");
if (optional_string_fred("+Special Hitpoints:", "$Name:")) {
@@ -3295,7 +3336,7 @@ int CFred_mission_save::save_objects() {
// Goober5000 - newer code to save off information about initially docked ships. ;)
if (object_is_docked(&Objects[shipp->objnum])) {
// possible incompatibility
if (Format_fs2_open == FSO_FORMAT_RETAIL && !dock_check_docked_one_on_one(&Objects[shipp->objnum])) {
if (Mission_save_format == FSO_FORMAT_RETAIL && !dock_check_docked_one_on_one(&Objects[shipp->objnum])) {
static bool warned = false;
if (!warned) {
CString text = "You are saving in the retail mission format, but \"";
@@ -3324,7 +3365,7 @@ int CFred_mission_save::save_objects() {
}
}
// check the ship flag about killing off the ship before a missino starts. Write out the appropriate
// check the ship flag about killing off the ship before a mission starts. Write out the appropriate
// variable if necessary
if (shipp->flags[Ship::Ship_Flags::Kill_before_mission]) {
if (optional_string_fred("+Destroy At:", "$Name:"))
@@ -3377,7 +3418,7 @@ int CFred_mission_save::save_objects() {
fout(" %d", shipp->score);
if (Format_fs2_open != FSO_FORMAT_RETAIL && shipp->assist_score_pct != 0) {
if (Mission_save_format != FSO_FORMAT_RETAIL && shipp->assist_score_pct != 0) {
fso_comment_push(";;FSO 3.6.10;;");
if (optional_string_fred("+Assist Score Percentage:")) {
parse_comments();
@@ -3452,7 +3493,9 @@ int CFred_mission_save::save_objects() {
return err;
}
int CFred_mission_save::save_players() {
int CFred_mission_save::save_players()
{
bool wrote_fso_data = false;
int i, j;
int var_idx;
int used_pool[MAX_WEAPON_TYPES];
@@ -3478,7 +3521,7 @@ int CFred_mission_save::save_players() {
}
// write out callsign list
if (Mission_callsign_count > 0) {
if (Mission_save_format != FSO_FORMAT_RETAIL && Mission_callsign_count > 0) {
fout("\n\n#Callsigns:\n");
// write them all out
@@ -3509,6 +3552,7 @@ int CFred_mission_save::save_players() {
if (strlen(Team_data[i].ship_list_variables[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].ship_list_variables[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("\t@%s\t", Sexp_variables[var_idx].variable_name);
} else {
@@ -3519,6 +3563,7 @@ int CFred_mission_save::save_players() {
if (strlen(Team_data[i].ship_count_variables[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].ship_count_variables[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("@%s\n", Sexp_variables[var_idx].variable_name);
} else {
@@ -3536,11 +3581,13 @@ int CFred_mission_save::save_players() {
fout(" (\n");
generate_weaponry_usage_list(i, used_pool);
for (j = 0; j < Team_data[i].num_weapon_choices; j++) {
// first output the weapon name or a variable that sets it
if (strlen(Team_data[i].weaponry_pool_variable[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].weaponry_pool_variable[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("\t@%s\t", Sexp_variables[var_idx].variable_name);
} else {
@@ -3553,6 +3600,7 @@ int CFred_mission_save::save_players() {
if (strlen(Team_data[i].weaponry_amount_variable[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].weaponry_amount_variable[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("@%s\n", Sexp_variables[var_idx].variable_name);
} else {
@@ -3574,6 +3622,12 @@ int CFred_mission_save::save_players() {
fout(")");
// sanity check
if (Mission_save_format == FSO_FORMAT_RETAIL && wrote_fso_data) {
// this is such an unlikely (and hard-to-fix) case that a warning should be sufficient
MessageBox(nullptr, "Warning: This mission contains variable-based team loadout information, but you are saving in the retail mission format. Retail FRED and FS2 will not be able to read this information.", "Incompatibility with retail mission format", MB_OK);
}
// Goober5000 - mjn.mixael's required weapon feature
bool uses_required_weapon = false;
for (j = 0; j < weapon_info_size(); j++) {
@@ -3582,7 +3636,7 @@ int CFred_mission_save::save_players() {
break;
}
}
if (uses_required_weapon) {
if (Mission_save_format != FSO_FORMAT_RETAIL && uses_required_weapon) {
if (optional_string_fred("+Required for mission:", "$Starting Shipname:"))
parse_comments(2);
else
@@ -3604,8 +3658,9 @@ int CFred_mission_save::save_players() {
return err;
}
int CFred_mission_save::save_plot_info() {
if (Format_fs2_open == FSO_FORMAT_RETAIL) {
int CFred_mission_save::save_plot_info()
{
if (Mission_save_format == FSO_FORMAT_RETAIL) {
if (optional_string_fred("#Plot Info")) {
parse_comments(2);
@@ -3654,7 +3709,8 @@ int CFred_mission_save::save_plot_info() {
return err;
}
int CFred_mission_save::save_reinforcements() {
int CFred_mission_save::save_reinforcements()
{
int i, j, type;
fred_parse_flag = 0;
@@ -3720,7 +3776,8 @@ int CFred_mission_save::save_reinforcements() {
return err;
}
void CFred_mission_save::save_single_dock_instance(ship *shipp, dock_instance *dock_ptr) {
void CFred_mission_save::save_single_dock_instance(ship *shipp, dock_instance *dock_ptr)
{
Assert(shipp && dock_ptr);
Assert(dock_ptr->docked_objp->type == OBJ_SHIP || dock_ptr->docked_objp->type == OBJ_START);
@@ -3752,7 +3809,8 @@ void CFred_mission_save::save_single_dock_instance(ship *shipp, dock_instance *d
fso_comment_pop(true);
}
void CFred_mission_save::save_turret_info(ship_subsys *ptr, int ship) {
void CFred_mission_save::save_turret_info(ship_subsys *ptr, int ship)
{
int i, z;
ship_weapon *wp = &ptr->weapons;
@@ -3833,7 +3891,8 @@ void CFred_mission_save::save_turret_info(ship_subsys *ptr, int ship) {
fso_comment_pop(true);
}
int CFred_mission_save::save_variables() {
int CFred_mission_save::save_variables()
{
char *type;
char number[] = "number";
char string[] = "string";
@@ -3847,7 +3906,7 @@ int CFred_mission_save::save_variables() {
// get count
int num_variables = sexp_variable_count();
if (Format_fs2_open == FSO_FORMAT_RETAIL) {
if (Mission_save_format == FSO_FORMAT_RETAIL) {
generate_special_explosion_block_variables();
num_block_vars = num_block_variables();
}
@@ -3875,7 +3934,7 @@ int CFred_mission_save::save_variables() {
fout("\n\t\t%d\t\t\"%s\"\t\t\"%s\"\t\t\"%s\"", i, Sexp_variables[i].variable_name, Sexp_variables[i].text, type);
// persistent and network variables
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
// Network variable - Karajorma
if (Sexp_variables[i].type & SEXP_VARIABLE_NETWORK) {
fout("\t\t\"%s\"", "network-variable");
@@ -3912,12 +3971,14 @@ int CFred_mission_save::save_variables() {
return err;
}
int CFred_mission_save::save_vector(vec3d &v) {
int CFred_mission_save::save_vector(vec3d &v)
{
fout(" %f, %f, %f", v.xyz.x, v.xyz.y, v.xyz.z);
return 0;
}
int CFred_mission_save::save_waypoints() {
int CFred_mission_save::save_waypoints()
{
//object *ptr;
fred_parse_flag = 0;
@@ -3935,39 +3996,41 @@ int CFred_mission_save::save_waypoints() {
parse_comments();
fout(" %s", jnp->GetName());
if (jnp->IsSpecialModel()) {
if (optional_string_fred("+Model File:", "$Jump Node:"))
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (jnp->IsSpecialModel()) {
if (optional_string_fred("+Model File:", "$Jump Node:"))
parse_comments();
else
fout("\n+Model File:");
int model = jnp->GetModelNumber();
polymodel *pm = model_get(model);
fout(" %s", pm->filename);
}
if (jnp->IsColored()) {
if (optional_string_fred("+Alphacolor:", "$Jump Node:"))
parse_comments();
else
fout("\n+Alphacolor:");
color jn_color = jnp->GetColor();
fout(" %u %u %u %u", jn_color.red, jn_color.green, jn_color.blue, jn_color.alpha);
}
int hidden_is_there = optional_string_fred("+Hidden:", "$Jump Node:");
if (hidden_is_there)
parse_comments();
else
fout("\n+Model File:");
int model = jnp->GetModelNumber();
polymodel *pm = model_get(model);
fout(" %s", pm->filename);
}
if (hidden_is_there || jnp->IsHidden()) {
if (!hidden_is_there)
fout("\n+Hidden:");
if (jnp->IsColored()) {
if (optional_string_fred("+Alphacolor:", "$Jump Node:"))
parse_comments();
else
fout("\n+Alphacolor:");
color jn_color = jnp->GetColor();
fout(" %u %u %u %u", jn_color.red, jn_color.green, jn_color.blue, jn_color.alpha);
}
int hidden_is_there = optional_string_fred("+Hidden:", "$Jump Node:");
if (hidden_is_there)
parse_comments();
if (hidden_is_there || jnp->IsHidden()) {
if (!hidden_is_there)
fout("\n+Hidden:");
if (jnp->IsHidden())
fout(" %s", "true");
else
fout(" %s", "false");
if (jnp->IsHidden())
fout(" %s", "true");
else
fout(" %s", "false");
}
}
fso_comment_pop();
@@ -3995,7 +4058,8 @@ int CFred_mission_save::save_waypoints() {
return err;
}
int CFred_mission_save::save_waypoint_list(waypoint_list *wp_list) {
int CFred_mission_save::save_waypoint_list(waypoint_list *wp_list)
{
Assert(wp_list != NULL);
SCP_vector<waypoint>::iterator ii;
@@ -4007,7 +4071,8 @@ int CFred_mission_save::save_waypoint_list(waypoint_list *wp_list) {
return 0;
}
int CFred_mission_save::save_wings() {
int CFred_mission_save::save_wings()
{
SCP_string sexp_out;
int i, j, z, ship, count = 0;
@@ -4027,7 +4092,7 @@ int CFred_mission_save::save_wings() {
fout(" %s", Wings[i].name);
// squad logo - Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if (strlen(Wings[i].wing_squad_filename) > 0) //-V805
{
if (optional_string_fred("+Squad Logo:", "$Name:"))
@@ -4072,7 +4137,7 @@ int CFred_mission_save::save_wings() {
if (z & SPECIAL_ARRIVAL_ANCHOR_FLAG) {
// get name
char tmp[NAME_LENGTH + 15];
stuff_special_arrival_anchor_name(tmp, z, Format_fs2_retail);
stuff_special_arrival_anchor_name(tmp, z, Mission_save_format == FSO_FORMAT_RETAIL ? 1 : 0);
// save it
fout(" %s", tmp);
@@ -4084,7 +4149,7 @@ int CFred_mission_save::save_wings() {
}
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if ((Wings[i].arrival_location == ARRIVE_FROM_DOCK_BAY) && (Wings[i].arrival_path_mask > 0)) {
int anchor_shipnum;
polymodel *pm;
@@ -4134,7 +4199,7 @@ int CFred_mission_save::save_wings() {
}
// Goober5000
if (Format_fs2_open != FSO_FORMAT_RETAIL) {
if (Mission_save_format != FSO_FORMAT_RETAIL) {
if ((Wings[i].departure_location == DEPART_AT_DOCK_BAY) && (Wings[i].departure_path_mask > 0)) {
int anchor_shipnum;
polymodel *pm;
+150 -81
View File
@@ -38,7 +38,8 @@
namespace fso {
namespace fred {
int CFred_mission_save::autosave_mission_file(char* pathname) {
int CFred_mission_save::autosave_mission_file(char* pathname)
{
char backup_name[256], name2[256];
int i;
@@ -60,7 +61,8 @@ int CFred_mission_save::autosave_mission_file(char* pathname) {
return err;
}
void CFred_mission_save::bypass_comment(const char* comment, const char* end) {
void CFred_mission_save::bypass_comment(const char* comment, const char* end)
{
char* ch = strstr(raw_ptr, comment);
if (ch != NULL) {
if (end != NULL) {
@@ -84,17 +86,20 @@ void CFred_mission_save::bypass_comment(const char* comment, const char* end) {
}
}
void CFred_mission_save::convert_special_tags_to_retail(char* text, int max_len) {
void CFred_mission_save::convert_special_tags_to_retail(char* text, int max_len)
{
replace_all(text, "$quote", "''", max_len);
replace_all(text, "$semicolon", ",", max_len);
}
void CFred_mission_save::convert_special_tags_to_retail(SCP_string& text) {
void CFred_mission_save::convert_special_tags_to_retail(SCP_string& text)
{
replace_all(text, "$quote", "''");
replace_all(text, "$semicolon", ",");
}
void CFred_mission_save::convert_special_tags_to_retail() {
void CFred_mission_save::convert_special_tags_to_retail()
{
int i, team, stage;
if (save_format != MissionFormat::RETAIL) {
@@ -123,7 +128,8 @@ void CFred_mission_save::convert_special_tags_to_retail() {
}
}
int CFred_mission_save::fout(const char* format, ...) {
int CFred_mission_save::fout(const char* format, ...)
{
SCP_string str;
va_list args;
@@ -139,7 +145,8 @@ int CFred_mission_save::fout(const char* format, ...) {
return 0;
}
int CFred_mission_save::fout_ext(const char* pre_str, const char* format, ...) {
int CFred_mission_save::fout_ext(const char* pre_str, const char* format, ...)
{
SCP_string str_scp;
SCP_string str_out_scp;
va_list args;
@@ -241,7 +248,8 @@ int CFred_mission_save::fout_ext(const char* pre_str, const char* format, ...) {
return 0;
}
int CFred_mission_save::fout_version(const char* format, ...) {
int CFred_mission_save::fout_version(const char* format, ...)
{
SCP_string str_scp;
char* ch = NULL;
va_list args;
@@ -250,6 +258,11 @@ int CFred_mission_save::fout_version(const char* format, ...) {
return err;
}
// if we're saving in retail format, we can completely skip this
if (save_format == MissionFormat::RETAIL) {
return 0;
}
// output the version first thing, but skip the special case where we use
// fout_version() for multiline value strings (typically indicated by an initial space)
if ((save_format == MissionFormat::COMPATIBILITY_MODE) && (*format != ' ') && !fso_ver_comment.empty()) {
@@ -330,7 +343,8 @@ int CFred_mission_save::fout_version(const char* format, ...) {
return 0;
}
void CFred_mission_save::parse_comments(int newlines) {
void CFred_mission_save::parse_comments(int newlines)
{
char* comment_start = NULL;
int state = 0, same_line = 0, first_comment = 1, tab = 0, flag = 0;
bool version_added = false;
@@ -507,7 +521,8 @@ void CFred_mission_save::parse_comments(int newlines) {
return;
}
void CFred_mission_save::save_ai_goals(ai_goal* goalp, int ship) {
void CFred_mission_save::save_ai_goals(ai_goal* goalp, int ship)
{
const char* str = NULL;
char buf[80];
int i, valid, flag = 1;
@@ -668,7 +683,8 @@ void CFred_mission_save::save_ai_goals(ai_goal* goalp, int ship) {
fso_comment_pop(true);
}
int CFred_mission_save::save_asteroid_fields() {
int CFred_mission_save::save_asteroid_fields()
{
int i;
fred_parse_flag = 0;
@@ -763,7 +779,8 @@ int CFred_mission_save::save_asteroid_fields() {
return err;
}
int CFred_mission_save::save_bitmaps() {
int CFred_mission_save::save_bitmaps()
{
int i;
uint j;
@@ -909,7 +926,8 @@ int CFred_mission_save::save_bitmaps() {
return err;
}
int CFred_mission_save::save_briefing() {
int CFred_mission_save::save_briefing()
{
int i, j, k, nb;
SCP_string sexp_out;
brief_stage* bs;
@@ -1097,7 +1115,8 @@ int CFred_mission_save::save_briefing() {
return err;
}
int CFred_mission_save::save_cmd_brief() {
int CFred_mission_save::save_cmd_brief()
{
int stage;
stage = 0;
@@ -1140,7 +1159,8 @@ int CFred_mission_save::save_cmd_brief() {
return err;
}
int CFred_mission_save::save_cmd_briefs() {
int CFred_mission_save::save_cmd_briefs()
{
int i;
for (i = 0; i < Num_teams; i++) {
@@ -1151,7 +1171,8 @@ int CFred_mission_save::save_cmd_briefs() {
return err;
}
void CFred_mission_save::fso_comment_push(const char* ver) {
void CFred_mission_save::fso_comment_push(const char* ver)
{
if (fso_ver_comment.empty()) {
fso_ver_comment.push_back(SCP_string(ver));
return;
@@ -1186,7 +1207,8 @@ void CFred_mission_save::fso_comment_push(const char* ver) {
}
}
void CFred_mission_save::fso_comment_pop(bool pop_all) {
void CFred_mission_save::fso_comment_pop(bool pop_all)
{
if (fso_ver_comment.empty()) {
return;
}
@@ -1199,7 +1221,8 @@ void CFred_mission_save::fso_comment_pop(bool pop_all) {
fso_ver_comment.pop_back();
}
int CFred_mission_save::save_common_object_data(object* objp, ship* shipp) {
int CFred_mission_save::save_common_object_data(object* objp, ship* shipp)
{
int j, z;
ship_subsys* ptr = NULL;
ship_info* sip = NULL;
@@ -1219,7 +1242,7 @@ int CFred_mission_save::save_common_object_data(object* objp, ship* shipp) {
}
// Goober5000
if (save_format != MissionFormat::RETAIL && (shipp->special_hitpoints)) {
if (save_format != MissionFormat::RETAIL && (shipp->special_hitpoints > 0)) {
temp_max_hull_strength = (float) shipp->special_hitpoints;
} else {
temp_max_hull_strength = sip->max_hull_strength;
@@ -1396,7 +1419,8 @@ void CFred_mission_save::save_custom_bitmap(const char* expected_string_640,
const char* expected_string_1024,
const char* string_field_640,
const char* string_field_1024,
int blank_lines) {
int blank_lines)
{
if (save_format != MissionFormat::RETAIL) {
if ((*string_field_640 != '\0') || (*string_field_1024 != '\0')) {
while (blank_lines-- > 0) {
@@ -1414,7 +1438,8 @@ void CFred_mission_save::save_custom_bitmap(const char* expected_string_640,
}
}
int CFred_mission_save::save_cutscenes() {
int CFred_mission_save::save_cutscenes()
{
char type[NAME_LENGTH];
SCP_string sexp_out;
@@ -1481,7 +1506,8 @@ int CFred_mission_save::save_cutscenes() {
return err;
}
int CFred_mission_save::save_debriefing() {
int CFred_mission_save::save_debriefing()
{
int j, i;
SCP_string sexp_out;
@@ -1541,7 +1567,8 @@ int CFred_mission_save::save_debriefing() {
return err;
}
int CFred_mission_save::save_events() {
int CFred_mission_save::save_events()
{
SCP_string sexp_out;
int i, j, add_flag;
@@ -1696,7 +1723,8 @@ int CFred_mission_save::save_events() {
return err;
}
int CFred_mission_save::save_fiction() {
int CFred_mission_save::save_fiction()
{
if (mission_has_fiction()) {
if (save_format != MissionFormat::RETAIL) {
if (optional_string_fred("#Fiction Viewer")) {
@@ -1787,7 +1815,8 @@ int CFred_mission_save::save_fiction() {
return err;
}
int CFred_mission_save::save_goals() {
int CFred_mission_save::save_goals()
{
SCP_string sexp_out;
int i;
@@ -1871,14 +1900,16 @@ int CFred_mission_save::save_goals() {
return err;
}
int CFred_mission_save::save_matrix(matrix& m) {
int CFred_mission_save::save_matrix(matrix& m)
{
fout("\n\t%f, %f, %f,\n", m.vec.rvec.xyz.x, m.vec.rvec.xyz.y, m.vec.rvec.xyz.z);
fout("\t%f, %f, %f,\n", m.vec.uvec.xyz.x, m.vec.uvec.xyz.y, m.vec.uvec.xyz.z);
fout("\t%f, %f, %f", m.vec.fvec.xyz.x, m.vec.fvec.xyz.y, m.vec.fvec.xyz.z);
return 0;
}
int CFred_mission_save::save_messages() {
int CFred_mission_save::save_messages()
{
int i;
fred_parse_flag = 0;
@@ -1958,7 +1989,8 @@ int CFred_mission_save::save_messages() {
return err;
}
int CFred_mission_save::save_mission_file(const char* pathname_in) {
int CFred_mission_save::save_mission_file(const char* pathname_in)
{
char backup_name[256], savepath[MAX_PATH_LEN], pathname[MAX_PATH_LEN];
strcpy_s(pathname, pathname_in);
@@ -1990,7 +2022,8 @@ int CFred_mission_save::save_mission_file(const char* pathname_in) {
return err;
}
int CFred_mission_save::save_mission_info() {
int CFred_mission_save::save_mission_info()
{
required_string_fred("#Mission Info");
parse_comments(0);
@@ -2343,7 +2376,8 @@ int CFred_mission_save::save_mission_info() {
return err;
}
void CFred_mission_save::save_mission_internal(const char* pathname) {
void CFred_mission_save::save_mission_internal(const char* pathname)
{
time_t rawtime;
time(&rawtime);
@@ -2416,7 +2450,8 @@ void CFred_mission_save::save_mission_internal(const char* pathname) {
mprintf(("Mission saving error code #%d\n", err));
}
int CFred_mission_save::save_music() {
int CFred_mission_save::save_music()
{
required_string_fred("#Music");
parse_comments(2);
@@ -2478,7 +2513,7 @@ int CFred_mission_save::save_music() {
Mission_music[SCORE_DEBRIEF_SUCCESS] < 0 ? "None"
: Spooled_music[Mission_music[SCORE_DEBRIEF_SUCCESS]].name);
}
if (Mission_music[SCORE_DEBRIEF_AVERAGE] != event_music_get_spooled_music_index("Average")) {
if (save_format != MissionFormat::RETAIL && Mission_music[SCORE_DEBRIEF_AVERAGE] != event_music_get_spooled_music_index("Average")) {
if (optional_string_fred("$Debriefing Average Music:")) {
parse_comments(1);
} else {
@@ -2519,6 +2554,9 @@ int CFred_mission_save::save_music() {
int CFred_mission_save::save_warp_params(WarpDirection direction, ship *shipp)
{
if (save_format == MissionFormat::RETAIL)
return err;
// for writing to file; c.f. parse_warp_params
const char *prefix = (direction == WarpDirection::WARP_IN) ? "$Warpin" : "$Warpout";
@@ -2613,7 +2651,8 @@ int CFred_mission_save::save_warp_params(WarpDirection direction, ship *shipp)
return err;
}
int CFred_mission_save::save_objects() {
int CFred_mission_save::save_objects()
{
SCP_string sexp_out;
int i, z;
ai_info* aip;
@@ -2677,7 +2716,7 @@ int CFred_mission_save::save_objects() {
}
// optional callsign
if (strlen(Fred_callsigns[i])) {
if (save_format != MissionFormat::RETAIL && strlen(Fred_callsigns[i])) {
fout("\n$Callsign: %s\n", Fred_callsigns[i]);
}
@@ -2685,7 +2724,7 @@ int CFred_mission_save::save_objects() {
parse_comments();
fout(" %s", Iff_info[shipp->team].iff_name);
if (Ship_info[shipp->ship_info_index].uses_team_colors) {
if (save_format != MissionFormat::RETAIL && Ship_info[shipp->ship_info_index].uses_team_colors) {
required_string_fred("$Team Color Setting:");
parse_comments();
fout(" %s", shipp->team_name.c_str());
@@ -3241,7 +3280,7 @@ int CFred_mission_save::save_objects() {
}
}
// check the ship flag about killing off the ship before a missino starts. Write out the appropriate
// check the ship flag about killing off the ship before a mission starts. Write out the appropriate
// variable if necessary
if (shipp->flags[Ship::Ship_Flags::Kill_before_mission]) {
if (optional_string_fred("+Destroy At:", "$Name:")) {
@@ -3375,7 +3414,9 @@ int CFred_mission_save::save_objects() {
return err;
}
int CFred_mission_save::save_players() {
int CFred_mission_save::save_players()
{
bool wrote_fso_data = false;
int i, j;
int var_idx;
int used_pool[MAX_WEAPON_TYPES];
@@ -3401,7 +3442,7 @@ int CFred_mission_save::save_players() {
}
// write out callsign list
if (Mission_callsign_count > 0) {
if (save_format != MissionFormat::RETAIL && Mission_callsign_count > 0) {
fout("\n\n#Callsigns:\n");
// write them all out
@@ -3432,6 +3473,7 @@ int CFred_mission_save::save_players() {
if (strlen(Team_data[i].ship_list_variables[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].ship_list_variables[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("\t@%s\t", Sexp_variables[var_idx].variable_name);
} else {
@@ -3442,6 +3484,7 @@ int CFred_mission_save::save_players() {
if (strlen(Team_data[i].ship_count_variables[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].ship_count_variables[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("@%s\n", Sexp_variables[var_idx].variable_name);
} else {
@@ -3459,11 +3502,13 @@ int CFred_mission_save::save_players() {
fout(" (\n");
generate_weaponry_usage_list_team(i, used_pool);
for (j = 0; j < Team_data[i].num_weapon_choices; j++) {
// first output the weapon name or a variable that sets it
if (strlen(Team_data[i].weaponry_pool_variable[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].weaponry_pool_variable[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("\t@%s\t", Sexp_variables[var_idx].variable_name);
} else {
@@ -3476,6 +3521,7 @@ int CFred_mission_save::save_players() {
if (strlen(Team_data[i].weaponry_amount_variable[j])) {
var_idx = get_index_sexp_variable_name(Team_data[i].weaponry_amount_variable[j]);
Assert(var_idx > -1 && var_idx < MAX_SEXP_VARIABLES);
wrote_fso_data = true;
fout("@%s\n", Sexp_variables[var_idx].variable_name);
} else {
@@ -3497,6 +3543,15 @@ int CFred_mission_save::save_players() {
fout(")");
// sanity check
if (save_format == MissionFormat::RETAIL && wrote_fso_data) {
// this is such an unlikely (and hard-to-fix) case that a warning should be sufficient
_viewport->dialogProvider->showButtonDialog(DialogType::Warning,
"Incompatibility with retail mission format",
"Warning: This mission contains variable-based team loadout information, but you are saving in the retail mission format. Retail FRED and FS2 will not be able to read this information.",
{ DialogButton::Ok });
}
// Goober5000 - mjn.mixael's required weapon feature
bool uses_required_weapon = false;
for (j = 0; j < static_cast<int>(Weapon_info.size()); j++) {
@@ -3505,7 +3560,7 @@ int CFred_mission_save::save_players() {
break;
}
}
if (uses_required_weapon) {
if (save_format != MissionFormat::RETAIL && uses_required_weapon) {
if (optional_string_fred("+Required for mission:", "$Starting Shipname:")) {
parse_comments(2);
} else {
@@ -3529,7 +3584,8 @@ int CFred_mission_save::save_players() {
return err;
}
int CFred_mission_save::save_plot_info() {
int CFred_mission_save::save_plot_info()
{
if (save_format == MissionFormat::RETAIL) {
if (optional_string_fred("#Plot Info")) {
parse_comments(2);
@@ -3579,7 +3635,8 @@ int CFred_mission_save::save_plot_info() {
return err;
}
int CFred_mission_save::save_reinforcements() {
int CFred_mission_save::save_reinforcements()
{
int i, j, type;
fred_parse_flag = 0;
@@ -3652,7 +3709,8 @@ int CFred_mission_save::save_reinforcements() {
return err;
}
void CFred_mission_save::save_single_dock_instance(ship* shipp, dock_instance* dock_ptr) {
void CFred_mission_save::save_single_dock_instance(ship* shipp, dock_instance* dock_ptr)
{
Assert(shipp && dock_ptr);
Assert(dock_ptr->docked_objp->type == OBJ_SHIP || dock_ptr->docked_objp->type == OBJ_START);
@@ -3689,7 +3747,8 @@ void CFred_mission_save::save_single_dock_instance(ship* shipp, dock_instance* d
fso_comment_pop(true);
}
void CFred_mission_save::save_turret_info(ship_subsys* ptr, int ship) {
void CFred_mission_save::save_turret_info(ship_subsys* ptr, int ship)
{
int i, z;
ship_weapon* wp = &ptr->weapons;
@@ -3781,7 +3840,8 @@ void CFred_mission_save::save_turret_info(ship_subsys* ptr, int ship) {
fso_comment_pop(true);
}
int CFred_mission_save::save_variables() {
int CFred_mission_save::save_variables()
{
char* type;
char number[] = "number";
char string[] = "string";
@@ -3864,12 +3924,14 @@ int CFred_mission_save::save_variables() {
return err;
}
int CFred_mission_save::save_vector(vec3d& v) {
int CFred_mission_save::save_vector(vec3d& v)
{
fout(" %f, %f, %f", v.xyz.x, v.xyz.y, v.xyz.z);
return 0;
}
int CFred_mission_save::save_waypoints() {
int CFred_mission_save::save_waypoints()
{
//object *ptr;
fred_parse_flag = 0;
@@ -3887,43 +3949,48 @@ int CFred_mission_save::save_waypoints() {
parse_comments();
fout(" %s", jnp->GetName());
if (jnp->IsSpecialModel()) {
if (optional_string_fred("+Model File:", "$Jump Node:")) {
if (save_format != MissionFormat::RETAIL) {
if (jnp->IsSpecialModel()) {
if (optional_string_fred("+Model File:", "$Jump Node:")) {
parse_comments();
}
else {
fout("\n+Model File:");
}
int model = jnp->GetModelNumber();
polymodel* pm = model_get(model);
fout(" %s", pm->filename);
}
if (jnp->IsColored()) {
if (optional_string_fred("+Alphacolor:", "$Jump Node:")) {
parse_comments();
}
else {
fout("\n+Alphacolor:");
}
color jn_color = jnp->GetColor();
fout(" %u %u %u %u", jn_color.red, jn_color.green, jn_color.blue, jn_color.alpha);
}
int hidden_is_there = optional_string_fred("+Hidden:", "$Jump Node:");
if (hidden_is_there) {
parse_comments();
} else {
fout("\n+Model File:");
}
int model = jnp->GetModelNumber();
polymodel* pm = model_get(model);
fout(" %s", pm->filename);
}
if (hidden_is_there || jnp->IsHidden()) {
if (!hidden_is_there) {
fout("\n+Hidden:");
}
if (jnp->IsColored()) {
if (optional_string_fred("+Alphacolor:", "$Jump Node:")) {
parse_comments();
} else {
fout("\n+Alphacolor:");
}
color jn_color = jnp->GetColor();
fout(" %u %u %u %u", jn_color.red, jn_color.green, jn_color.blue, jn_color.alpha);
}
int hidden_is_there = optional_string_fred("+Hidden:", "$Jump Node:");
if (hidden_is_there) {
parse_comments();
}
if (hidden_is_there || jnp->IsHidden()) {
if (!hidden_is_there) {
fout("\n+Hidden:");
}
if (jnp->IsHidden()) {
fout(" %s", "true");
} else {
fout(" %s", "false");
if (jnp->IsHidden()) {
fout(" %s", "true");
}
else {
fout(" %s", "false");
}
}
}
@@ -3952,7 +4019,8 @@ int CFred_mission_save::save_waypoints() {
return err;
}
int CFred_mission_save::save_waypoint_list(waypoint_list* wp_list) {
int CFred_mission_save::save_waypoint_list(waypoint_list* wp_list)
{
Assert(wp_list != NULL);
SCP_vector<waypoint>::iterator ii;
@@ -3964,7 +4032,8 @@ int CFred_mission_save::save_waypoint_list(waypoint_list* wp_list) {
return 0;
}
int CFred_mission_save::save_wings() {
int CFred_mission_save::save_wings()
{
SCP_string sexp_out;
int i, j, z, count = 0;
+6 -6
View File
@@ -29,20 +29,20 @@ class IntelParseTest : public test::FSTestFixture {
// Commonly used expected intel data entries.
static intel_data expected_foo = {
"Foo name", // XSTR id 3000
"Foo desc", // XSTR id 3001
"Foo name default", // XSTR id 3000
"Foo desc default", // XSTR id 3001
"Foo anim",
IIF_IN_TECH_DATABASE | IIF_DEFAULT_IN_TECH_DATABASE
};
static intel_data expected_bar = {
"Bar name", // XSTR id 3002
"Bar desc", // XSTR id 3003
"Bar name default", // XSTR id 3002
"Bar desc default", // XSTR id 3003
"Bar anim",
0
};
static intel_data expected_baz = {
"Baz name", // XSTR id 3004
"Baz desc", // XSTR id 3005
"Baz name default", // XSTR id 3004
"Baz desc default", // XSTR id 3005
"Baz anim",
IIF_IN_TECH_DATABASE | IIF_DEFAULT_IN_TECH_DATABASE
};