Skip to content

Commit 975ce27

Browse files
authored
QtFRED large ship collision group mission flag (scp-fs2open#7425)
* large ship collision group mission flag * update help doc
1 parent 6c0d490 commit 975ce27

10 files changed

Lines changed: 113 additions & 1 deletion

File tree

code/mission/mission_flags.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace Mission {
3636
Neb2_fog_color_override, // Whether to use explicit fog colors instead of checking the palette - Goober5000
3737
Fullneb_background_bitmaps, // Show background bitmaps despite fullneb
3838
Preload_subspace, // Preload the subspace tunnel for both the sexp and specs checkbox (for scripts) - MjnMixael
39+
Large_ships_no_collide_by_default, // Automatically puts all large ships in a shared collision group
3940

4041
NUM_VALUES
4142
};

code/mission/missionparse.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ SCP_unordered_set<int> Fred_migrated_immobile_ships;
203203
int Num_path_restrictions;
204204
path_restriction_t Path_restrictions[MAX_PATH_RESTRICTIONS];
205205

206+
constexpr int DEFAULT_LARGE_SHIP_NO_COLLIDE_COLLISION_GROUP = 0;
207+
206208
extern int debrief_find_persona_index();
207209

208210
static bool mission_has_layer_name(const mission* pm, const SCP_string& layerName) {
@@ -418,7 +420,8 @@ flag_def_list_new<Mission::Mission_Flags> Parse_mission_flags[] = {
418420
{"Toggle Starting in Chase View", Mission::Mission_Flags::Toggle_start_chase_view, true, false},
419421
{"Nebula Fog Color Override", Mission::Mission_Flags::Neb2_fog_color_override, true, true},
420422
{"Full Nebula Background Bitmaps", Mission::Mission_Flags::Fullneb_background_bitmaps, true, true},
421-
{"Preload Subspace Tunnel", Mission::Mission_Flags::Preload_subspace, true, false}
423+
{"Preload Subspace Tunnel", Mission::Mission_Flags::Preload_subspace, true, false},
424+
{"Large Ships Do Not Collide By Default", Mission::Mission_Flags::Large_ships_no_collide_by_default, true, false}
422425
};
423426

424427
parse_object_flag_description<Mission::Mission_Flags> Parse_mission_flag_descriptions[] = {
@@ -452,6 +455,7 @@ parse_object_flag_description<Mission::Mission_Flags> Parse_mission_flag_descrip
452455
{Mission::Mission_Flags::Neb2_fog_color_override, "Whether to use explicit fog colors instead of checking the palette"},
453456
{Mission::Mission_Flags::Fullneb_background_bitmaps, "Show background bitmaps despite full nebula"},
454457
{Mission::Mission_Flags::Preload_subspace, "Preload the subspace tunnel for both the sexp and specs checkbox"},
458+
{Mission::Mission_Flags::Large_ships_no_collide_by_default, "Automatically places all large ships in the configured collision group, preventing large ships from colliding with each other"},
455459
};
456460

457461
const size_t Num_parse_mission_flags = sizeof(Parse_mission_flags) / sizeof(flag_def_list_new<Mission::Mission_Flags>);
@@ -865,6 +869,18 @@ void parse_mission_info(mission *pm, bool basic = false)
865869
stuff_int(&pm->contrail_threshold);
866870
}
867871

872+
if (optional_string("+Large Ship Collision Group:")) {
873+
stuff_int(&pm->large_ship_no_collide_collision_group);
874+
875+
if (pm->large_ship_no_collide_collision_group < 0 || pm->large_ship_no_collide_collision_group > 31) {
876+
WarningEx(LOCATION,
877+
"Invalid large ship collision group id %d specified. Valid IDs range from 0 to 31. Using group %d instead.\n",
878+
pm->large_ship_no_collide_collision_group,
879+
DEFAULT_LARGE_SHIP_NO_COLLIDE_COLLISION_GROUP);
880+
pm->large_ship_no_collide_collision_group = DEFAULT_LARGE_SHIP_NO_COLLIDE_COLLISION_GROUP;
881+
}
882+
}
883+
868884
if (optional_string("+Volumetric Nebula:")) {
869885
pm->volumetrics.emplace().parse_volumetric_nebula();
870886
}
@@ -2259,6 +2275,11 @@ int parse_create_object_sub(p_object *p_objp, bool standalone_ship)
22592275
// Goober5000 - set the collision group if one was provided
22602276
Objects[objnum].collision_group_id = p_objp->collision_group_id;
22612277

2278+
// Mission-level performance helper: large ships may be grouped so they skip mutual collision checks.
2279+
if (The_mission.flags[Mission::Mission_Flags::Large_ships_no_collide_by_default] && sip->is_big_or_huge()) {
2280+
Objects[objnum].collision_group_id |= (1 << The_mission.large_ship_no_collide_collision_group);
2281+
}
2282+
22622283
// Goober5000 - set some fields that the mission log might need (if logged via parse_bring_in_docked_wing just below)
22632284
shipp->display_name = p_objp->display_name;
22642285
shipp->alt_type_index = p_objp->alt_type_index;
@@ -7210,6 +7231,7 @@ void mission::Reset()
72107231

72117232
envmap_name[ 0 ] = '\0';
72127233
contrail_threshold = CONTRAIL_THRESHOLD_DEFAULT;
7234+
large_ship_no_collide_collision_group = DEFAULT_LARGE_SHIP_NO_COLLIDE_COLLISION_GROUP;
72137235
ambient_light_level = DEFAULT_AMBIENT_LIGHT_LEVEL;
72147236
sound_environment.id = -1;
72157237

@@ -9591,6 +9613,9 @@ bool check_for_24_3_data()
95919613

95929614
bool check_for_25_1_data()
95939615
{
9616+
if (The_mission.flags[Mission::Mission_Flags::Large_ships_no_collide_by_default])
9617+
return true;
9618+
95949619
if (count_items_with_value(Props) > 0)
95959620
return true;
95969621

code/mission/missionparse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ typedef struct mission {
207207
char envmap_name[MAX_FILENAME_LEN];
208208
int skybox_flags;
209209
int contrail_threshold;
210+
int large_ship_no_collide_collision_group;
210211
int ambient_light_level;
211212
std::optional<volumetric_nebula> volumetrics;
212213
sound_env sound_environment;

code/missioneditor/missionsave.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2568,6 +2568,10 @@ int Fred_mission_save::save_mission_info()
25682568
if (The_mission.contrail_threshold != CONTRAIL_THRESHOLD_DEFAULT) {
25692569
fout("\n$Contrail Speed Threshold: %d\n", The_mission.contrail_threshold);
25702570
}
2571+
2572+
if (The_mission.flags[Mission::Mission_Flags::Large_ships_no_collide_by_default]) {
2573+
fout("\n+Large Ship Collision Group: %d\n", The_mission.large_ship_no_collide_collision_group);
2574+
}
25712575
}
25722576

25732577
{

qtfred/help-src/doc/dialogs/MissionSpecsDialog.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,15 @@ <h2>Flags</h2>
140140
box to find a specific flag by name, or use <strong>Select All</strong> /
141141
<strong>Select None</strong> to bulk-toggle. Hover over any flag label for a tooltip
142142
description.</p>
143+
<p>Some flags reveal an additional control when enabled:</p>
144+
<table>
145+
<tr><th>Flag</th><th>Control</th><th>Description</th></tr>
146+
<tr><td>Large Ships Do Not Collide By Default</td>
147+
<td>Large Ship Collision Group</td>
148+
<td>Collision group ID (0–31) that large and huge ships are automatically
149+
placed into when the mission loads. Ships sharing the same group skip
150+
collision checks against each other, reducing physics overhead in
151+
missions with many capital ships. Default is 0.</td></tr>
152+
</table>
143153
</body>
144154
</html>

qtfred/src/mission/dialogs/MissionSpecDialogModel.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void MissionSpecDialogModel::initializeData() {
7070

7171
_m_contrail_threshold = The_mission.contrail_threshold;
7272
_m_contrail_threshold_flag = (_m_contrail_threshold != CONTRAIL_THRESHOLD_DEFAULT);
73+
_m_large_ship_no_collide_collision_group = The_mission.large_ship_no_collide_collision_group;
7374

7475
_m_custom_data = The_mission.custom_data;
7576
_m_custom_strings = The_mission.custom_strings;
@@ -125,6 +126,7 @@ bool MissionSpecDialogModel::apply() {
125126
The_mission.support_ships.max_support_ships = (_m_disallow_support) ? 0 : -1;
126127
The_mission.support_ships.max_hull_repair_val = _m_max_hull_repair_val;
127128
The_mission.support_ships.max_subsys_repair_val = _m_max_subsys_repair_val;
129+
The_mission.large_ship_no_collide_collision_group = _m_large_ship_no_collide_collision_group;
128130

129131
// Copy mission flags
130132
The_mission.flags = _m_flags;
@@ -418,6 +420,22 @@ void MissionSpecDialogModel::setMissionFlagDirect(Mission::Mission_Flags flag, b
418420
}
419421
}
420422

423+
void MissionSpecDialogModel::setLargeShipNoCollideCollisionGroup(int group)
424+
{
425+
if (group < 0) {
426+
group = 0;
427+
} else if (group > 31) {
428+
group = 31;
429+
}
430+
431+
modify(_m_large_ship_no_collide_collision_group, group);
432+
}
433+
434+
int MissionSpecDialogModel::getLargeShipNoCollideCollisionGroup() const
435+
{
436+
return _m_large_ship_no_collide_collision_group;
437+
}
438+
421439
bool MissionSpecDialogModel::getMissionFlag(Mission::Mission_Flags flag) const {
422440
return _m_flags[flag];
423441
}

qtfred/src/mission/dialogs/MissionSpecDialogModel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class MissionSpecDialogModel : public AbstractDialogModel {
4242
float _m_max_subsys_repair_val;
4343
bool _m_contrail_threshold_flag;
4444
int _m_contrail_threshold;
45+
int _m_large_ship_no_collide_collision_group;
4546
SCP_map<SCP_string, SCP_string> _m_custom_data;
4647
SCP_vector<custom_string> _m_custom_strings;
4748
sound_env _m_sound_env;
@@ -119,6 +120,8 @@ class MissionSpecDialogModel : public AbstractDialogModel {
119120

120121
void setMissionFlag(const SCP_string& flag_name, bool enabled);
121122
void setMissionFlagDirect(Mission::Mission_Flags flag, bool enabled);
123+
void setLargeShipNoCollideCollisionGroup(int group);
124+
int getLargeShipNoCollideCollisionGroup() const;
122125
bool getMissionFlag(Mission::Mission_Flags flag) const;
123126
const SCP_vector<std::pair<SCP_string, bool>>& getMissionFlagsList();
124127
static SCP_vector<std::pair<SCP_string, SCP_string>> getMissionFlagDescriptions();

qtfred/src/ui/dialogs/MissionSpecDialog.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ void MissionSpecDialog::initFlagList()
134134
// per flag immediate apply to the model
135135
connect(ui->flagList, &fso::fred::FlagListWidget::flagToggled, this, [this](const QString& name, bool checked) {
136136
_model->setMissionFlag(name.toUtf8().constData(), checked);
137+
updateLargeShipCollisionGroup();
137138
});
138139
}
139140

@@ -149,6 +150,15 @@ void MissionSpecDialog::updateFlags()
149150
}
150151

151152
ui->flagList->setFlags(toWidget);
153+
updateLargeShipCollisionGroup();
154+
}
155+
156+
void MissionSpecDialog::updateLargeShipCollisionGroup()
157+
{
158+
const auto enabled = _model->getMissionFlag(Mission::Mission_Flags::Large_ships_no_collide_by_default);
159+
ui->largeShipCollisionGroupLabel->setVisible(enabled);
160+
ui->largeShipCollisionGroup->setVisible(enabled);
161+
ui->largeShipCollisionGroup->setValue(_model->getLargeShipNoCollideCollisionGroup());
152162
}
153163

154164
void MissionSpecDialog::updateMissionType() {
@@ -433,6 +443,11 @@ void MissionSpecDialog::on_musicPackCombo_currentIndexChanged(int index) {
433443
_model->setSubEventMusic(subMusic);
434444
}
435445

446+
void MissionSpecDialog::on_largeShipCollisionGroup_valueChanged(int value)
447+
{
448+
_model->setLargeShipNoCollideCollisionGroup(value);
449+
}
450+
436451
void MissionSpecDialog::on_aiProfileCombo_currentIndexChanged(int index)
437452
{
438453
auto aipIndex = ui->aiProfileCombo->itemData(index).value<int>();

qtfred/src/ui/dialogs/MissionSpecDialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ private slots:
6464

6565
// Right column
6666
// flags are dynamically generated and connected
67+
void on_largeShipCollisionGroup_valueChanged(int value);
6768
void on_aiProfileCombo_currentIndexChanged(int index);
6869

6970
// General
@@ -84,6 +85,7 @@ private slots:
8485

8586
void initFlagList();
8687
void updateFlags();
88+
void updateLargeShipCollisionGroup();
8789

8890
void updateMissionType();
8991
void updateCmdMessage();

qtfred/ui/MissionSpecDialog.ui

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,39 @@
822822
</property>
823823
</widget>
824824
</item>
825+
<item>
826+
<layout class="QFormLayout" name="largeShipCollisionGroupLayout">
827+
<property name="leftMargin">
828+
<number>0</number>
829+
</property>
830+
<property name="topMargin">
831+
<number>0</number>
832+
</property>
833+
<property name="rightMargin">
834+
<number>0</number>
835+
</property>
836+
<property name="bottomMargin">
837+
<number>0</number>
838+
</property>
839+
<item row="0" column="0">
840+
<widget class="QLabel" name="largeShipCollisionGroupLabel">
841+
<property name="text">
842+
<string>Large Ship Collision Group</string>
843+
</property>
844+
</widget>
845+
</item>
846+
<item row="0" column="1">
847+
<widget class="QSpinBox" name="largeShipCollisionGroup">
848+
<property name="minimum">
849+
<number>0</number>
850+
</property>
851+
<property name="maximum">
852+
<number>31</number>
853+
</property>
854+
</widget>
855+
</item>
856+
</layout>
857+
</item>
825858
</layout>
826859
</widget>
827860
</item>

0 commit comments

Comments
 (0)