Skip to content

Commit dbd63e2

Browse files
committed
have the campaign editor pass the links to save properly
1 parent ebb003b commit dbd63e2

File tree

4 files changed

+139
-47
lines changed

4 files changed

+139
-47
lines changed

code/missioneditor/campaignsave.cpp

Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// Bodies copied from the old implementations in missionsave.cpp,
1212
// unchanged except for the new class name and include.
13-
int Fred_campaign_save::save_campaign_file(const char* pathname)
13+
int Fred_campaign_save::save_campaign_file(const char* pathname, const SCP_vector<campaign_link>& links)
1414
{
1515
// This is original FRED code. These were moved to the call sites as the data should be fully
1616
// prepared before calling this function.
@@ -162,55 +162,100 @@ int Fred_campaign_save::save_campaign_file(const char* pathname)
162162
bypass_comment(";;FSO 3.6.8;; +Debriefing Persona Index:");
163163
}
164164

165-
// new save cmission sexps
166-
if (optional_string_fred("+Formula:", "$Mission:")) {
167-
parse_comments();
168-
} else {
169-
fout("\n+Formula:");
165+
// save campaign link sexp
166+
bool mission_loop = false;
167+
bool mission_fork = false;
168+
int flag = 0;
169+
for (auto& link : links) {
170+
if (link.from == i) {
171+
if (!flag) {
172+
if (optional_string_fred("+Formula:", "$Mission:"))
173+
parse_comments();
174+
else
175+
fout("\n+Formula:");
176+
177+
fout(" ( cond\n");
178+
flag = 1;
179+
}
180+
181+
// save_campaign_sexp(Links[j].sexp, Campaign.missions[Links[j].to].name);
182+
if (link.is_mission_loop) {
183+
mission_loop = true;
184+
} else if (link.is_mission_fork && (save_config.save_format != MissionFormat::RETAIL)) {
185+
mission_fork = true;
186+
} else {
187+
save_campaign_sexp(link.sexp, link.to);
188+
}
189+
}
170190
}
171191

172-
{
173-
SCP_string sexp_out{};
174-
convert_sexp_to_string(sexp_out, cm.formula, SEXP_SAVE_MODE);
175-
fout(" %s", sexp_out.c_str());
192+
if (flag) {
193+
fout(")");
176194
}
177195

178-
bool mission_loop = cm.flags & CMISSION_FLAG_HAS_LOOP;
179-
180-
Assertion(cm.flags ^ CMISSION_FLAG_HAS_FORK,
181-
"scpFork campaigns cannot be saved, use axemFork.\n Should be detected on load.");
182-
183-
if (mission_loop) {
184-
required_string_fred("\n+Mission Loop:");
196+
// now save campaign loop sexp
197+
if (mission_loop || mission_fork) {
198+
if (mission_loop)
199+
required_string_fred("\n+Mission Loop:");
200+
else
201+
required_string_fred("\n+Mission Fork:");
185202
parse_comments();
186203

187-
if (cm.mission_branch_desc) {
188-
required_string_fred("+Mission Loop Text:");
189-
parse_comments();
190-
fout_ext("\n", "%s", cm.mission_branch_desc);
191-
fout("\n$end_multi_text");
192-
}
193-
194-
if (cm.mission_branch_brief_anim) {
195-
required_string_fred("+Mission Loop Brief Anim:");
196-
parse_comments();
197-
fout_ext("\n", "%s", cm.mission_branch_brief_anim);
198-
fout("\n$end_multi_text");
204+
int num_mission_special = 0;
205+
for (auto& link : links) {
206+
if ((link.from == i) && (link.is_mission_loop || link.is_mission_fork)) {
207+
208+
num_mission_special++;
209+
210+
if ((num_mission_special == 1) && link.mission_branch_txt) {
211+
if (mission_loop)
212+
required_string_fred("+Mission Loop Text:");
213+
else
214+
required_string_fred("+Mission Fork Text:");
215+
parse_comments();
216+
fout_ext("\n", "%s", link.mission_branch_txt);
217+
fout("\n$end_multi_text");
218+
}
219+
220+
if ((num_mission_special == 1) && link.mission_branch_brief_anim) {
221+
if (mission_loop)
222+
required_string_fred("+Mission Loop Brief Anim:");
223+
else
224+
required_string_fred("+Mission Fork Brief Anim:");
225+
parse_comments();
226+
fout_ext("\n", "%s", link.mission_branch_brief_anim);
227+
fout("\n$end_multi_text");
228+
}
229+
230+
if ((num_mission_special == 1) && link.mission_branch_brief_sound) {
231+
if (mission_loop)
232+
required_string_fred("+Mission Loop Brief Sound:");
233+
else
234+
required_string_fred("+Mission Fork Brief Sound:");
235+
parse_comments();
236+
fout_ext("\n", "%s", link.mission_branch_brief_sound);
237+
fout("\n$end_multi_text");
238+
}
239+
240+
if (num_mission_special == 1) {
241+
// write out mission loop formula
242+
fout("\n+Formula:");
243+
fout(" ( cond\n");
244+
save_campaign_sexp(link.sexp, link.to);
245+
fout(")");
246+
}
247+
if (mission_fork) {
248+
fout("Option: ", Campaign.missions[link.to].name);
249+
}
250+
}
199251
}
200-
201-
if (cm.mission_branch_brief_sound) {
202-
required_string_fred("+Mission Loop Brief Sound:");
203-
parse_comments();
204-
fout_ext("\n", "%s", cm.mission_branch_brief_sound);
205-
fout("\n$end_multi_text");
206-
}
207-
208-
// write out mission loop formula
209-
fout("\n+Formula:");
210-
{
211-
SCP_string sexp_out{};
212-
convert_sexp_to_string(sexp_out, cm.mission_loop_formula, SEXP_SAVE_MODE);
213-
fout(" %s", sexp_out.c_str());
252+
if (mission_loop && num_mission_special > 1) {
253+
char buffer[1024];
254+
sprintf(buffer,
255+
"Multiple branching loop error from mission %s\nEdit campaign for *at most* 1 loop from each "
256+
"mission.",
257+
cm.name);
258+
Message(os::dialogs::MESSAGEBOX_ERROR, buffer);
214259
}
215260
}
216261

code/missioneditor/campaignsave.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
#pragma once
22
#include "missionsave.h"
33

4+
typedef struct campaign_link {
5+
int from; // index of source mission
6+
int to; // index of mission link leads to
7+
int sexp; // sexp index of condition that allows this branch
8+
int node; // node tracker when link is in sexp tree window
9+
bool is_mission_loop; // whether link leads to mission loop
10+
bool is_mission_fork; // whether link leads to mission fork
11+
char* mission_branch_txt; // text describing mission loop
12+
char* mission_branch_brief_anim; // filename of anim to play in the brief
13+
char* mission_branch_brief_sound; // filename of anim to play in the brief
14+
} campaign_link;
15+
416
class Fred_campaign_save : public Fred_mission_save {
517
public:
618
/**
@@ -15,7 +27,7 @@ class Fred_campaign_save : public Fred_mission_save {
1527
*
1628
* @see save_mission_internal()
1729
*/
18-
int save_campaign_file(const char* pathname);
30+
int save_campaign_file(const char* pathname, const SCP_vector<campaign_link>& links);
1931

2032
private:
2133
/**

fred2/campaigntreewnd.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,24 @@ void campaign_tree_wnd::OnCpgnFileSave()
206206
Campaign_tree_formp->save_tree(); // flush all changes so they get saved.
207207
Campaign_tree_viewp->sort_elements();
208208

209-
if (save.save_campaign_file(full_path))
209+
SCP_vector<campaign_link> links;
210+
for (int i = 0; i < Total_links; i++) {
211+
campaign_link link{
212+
Links[i].from,
213+
Links[i].to,
214+
Links[i].sexp,
215+
Links[i].node,
216+
Links[i].is_mission_loop,
217+
Links[i].is_mission_fork,
218+
Links[i].mission_branch_txt,
219+
Links[i].mission_branch_brief_anim,
220+
Links[i].mission_branch_brief_sound
221+
};
222+
223+
links.emplace_back(link);
224+
}
225+
226+
if (save.save_campaign_file(full_path, links))
210227
{
211228
MessageBox("An error occured while saving!", "Error", MB_OK | MB_ICONEXCLAMATION);
212229
return;
@@ -258,7 +275,22 @@ void campaign_tree_wnd::OnCpgnFileSaveAs()
258275
Campaign_tree_formp->save_tree(); // flush all changes so they get saved.
259276
Campaign_tree_viewp->sort_elements();
260277

261-
if (save.save_campaign_file((LPCSTR)dlg.GetPathName()))
278+
SCP_vector<campaign_link> links;
279+
for (int i = 0; i < Total_links; i++) {
280+
campaign_link link{Links[i].from,
281+
Links[i].to,
282+
Links[i].sexp,
283+
Links[i].node,
284+
Links[i].is_mission_loop,
285+
Links[i].is_mission_fork,
286+
Links[i].mission_branch_txt,
287+
Links[i].mission_branch_brief_anim,
288+
Links[i].mission_branch_brief_sound};
289+
290+
links.emplace_back(link);
291+
}
292+
293+
if (save.save_campaign_file((LPCSTR)dlg.GetPathName(), links))
262294
{
263295
MessageBox("An error occured while saving!", "Error", MB_OK | MB_ICONEXCLAMATION);
264296
return;

qtfred/src/mission/dialogs/CampaignEditorDialogModel.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,10 @@ bool CampaignEditorDialogModel::_saveTo(QString file) const {
603603
} else {
604604
save.set_save_format(MissionFormat::STANDARD);
605605
}*/
606-
return !save.save_campaign_file(qPrintable(file.replace('/',DIR_SEPARATOR_CHAR)));
606+
607+
// TODO create the links vector properly after the campaign editor update is merged
608+
SCP_vector<campaign_link> links;
609+
return !save.save_campaign_file(qPrintable(file.replace('/',DIR_SEPARATOR_CHAR)), links);
607610
}
608611

609612
bool CampaignEditorDialogModel::deleteLinksTo(const CampaignMissionData &target) {

0 commit comments

Comments
 (0)