Skip to content

Commit b9c0a1d

Browse files
committed
fix a few campaign editor bugs
1. Properly initialize campaign links and elements so that stale values don't stick around from previously loaded campaigns. 2. Clear internal flag bits from campaign missions to prevent invalid state from being loaded from a campaign file. 3. Properly check the main hall when saving flags in retail format. 4. Clean up parsing and saving of mission loop data, which had been broken ever since retail. Add compatibility checks for the old format.
1 parent fbf5870 commit b9c0a1d

4 files changed

Lines changed: 67 additions & 31 deletions

File tree

code/mission/missioncampaign.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,9 @@ int mission_campaign_load(const char* filename, const char* full_path, player* p
550550
cm->main_hall = "1";
551551
}
552552

553+
// clear any other flag bits to prevent bogus values causing surprises
554+
cm->flags &= CMISSION_EXTERNAL_FLAG_MASK;
555+
553556
// Goober5000 - new main hall stuff!
554557
// Updated by CommanderDJ
555558
if (optional_string("+Main Hall:")) {
@@ -610,12 +613,16 @@ int mission_campaign_load(const char* filename, const char* full_path, player* p
610613

611614
cm->mission_branch_brief_anim = NULL;
612615
if ( optional_string("+Mission Loop Brief Anim:") || optional_string("+Mission Fork Brief Anim:") ) {
613-
cm->mission_branch_brief_anim = stuff_and_malloc_string(F_MULTITEXT, NULL);
616+
ignore_white_space(); // it might be on the next line
617+
cm->mission_branch_brief_anim = stuff_and_malloc_string(F_FILESPEC, nullptr);
618+
(void)optional_string("$end_multi_text"); // consume the unneeded ending token
614619
}
615620

616621
cm->mission_branch_brief_sound = NULL;
617622
if ( optional_string("+Mission Loop Brief Sound:") || optional_string("+Mission Fork Brief Sound:") ) {
618-
cm->mission_branch_brief_sound = stuff_and_malloc_string(F_MULTITEXT, NULL);
623+
ignore_white_space(); // it might be on the next line
624+
cm->mission_branch_brief_sound = stuff_and_malloc_string(F_FILESPEC, nullptr);
625+
(void)optional_string("$end_multi_text"); // consume the unneeded ending token
619626
}
620627

621628
cm->mission_loop_formula = -1;

code/missioneditor/campaignsave.cpp

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ int Fred_campaign_save::save_campaign_file(const char* pathname, const SCP_vecto
134134
fout(" %s", cm.main_hall.c_str());
135135
} else {
136136
// save Bastion flag properly
137-
fout(" %d", flags_to_save | ((!cm.main_hall.empty()) ? CMISSION_FLAG_BASTION : 0));
137+
fout(" %d", flags_to_save | ((!cm.main_hall.empty() && cm.main_hall != "0") ? CMISSION_FLAG_BASTION : 0));
138138
}
139139

140140
if (!cm.substitute_main_hall.empty()) {
@@ -218,23 +218,35 @@ int Fred_campaign_save::save_campaign_file(const char* pathname, const SCP_vecto
218218
}
219219

220220
if ((num_mission_special == 1) && link.mission_branch_brief_anim) {
221-
if (mission_loop)
222-
required_string_fred("+Mission Loop Brief Anim:");
221+
auto str = mission_loop ? "+Mission Loop Brief Anim:" : "+Mission Fork Brief Anim:";
222+
if (optional_string_fred(str))
223+
parse_comments();
223224
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");
225+
fout("\n%s", str);
226+
227+
if (save_config.save_format != MissionFormat::RETAIL) {
228+
fout(" %s", link.mission_branch_brief_anim);
229+
} else {
230+
// previous formats used multitext, which causes problems
231+
fout_ext("\n", "%s", link.mission_branch_brief_anim);
232+
fout("\n$end_multi_text");
233+
}
228234
}
229235

230236
if ((num_mission_special == 1) && link.mission_branch_brief_sound) {
231-
if (mission_loop)
232-
required_string_fred("+Mission Loop Brief Sound:");
237+
auto str = mission_loop ? "+Mission Loop Brief Sound:" : "+Mission Fork Brief Sound:";
238+
if (optional_string_fred(str))
239+
parse_comments();
233240
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");
241+
fout("\n%s", str);
242+
243+
if (save_config.save_format != MissionFormat::RETAIL) {
244+
fout(" %s", link.mission_branch_brief_sound);
245+
} else {
246+
// previous formats used multitext, which causes problems
247+
fout_ext("\n", "%s", link.mission_branch_brief_sound);
248+
fout("\n$end_multi_text");
249+
}
238250
}
239251

240252
if (num_mission_special == 1) {

fred2/campaigntreeview.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,30 @@ campaign_tree_link Links[MAX_CAMPAIGN_TREE_LINKS];
3232
LOCAL CRect Dragging_rect;
3333
LOCAL CSize Rect_offset, Last_draw_size;
3434

35+
void init_link(campaign_tree_link &link, int from, int to)
36+
{
37+
link.from = from;
38+
link.to = to;
39+
link.sexp = Locked_sexp_true;
40+
link.node = -1;
41+
link.from_pos = -1;
42+
link.to_pos = -1;
43+
link.is_mission_loop = false;
44+
link.is_mission_fork = false;
45+
link.mission_branch_txt = nullptr;
46+
link.mission_branch_brief_anim = nullptr;
47+
link.mission_branch_brief_sound = nullptr;
48+
link.p1 = CPoint();
49+
link.p2 = CPoint();
50+
}
51+
52+
void init_element(campaign_tree_element &element)
53+
{
54+
element.from_links = 0;
55+
element.to_links = 0;
56+
element.box = CRect();
57+
}
58+
3559
/////////////////////////////////////////////////////////////////////////////
3660
// campaign_tree_view
3761

@@ -247,12 +271,9 @@ void stuff_link_with_formula(int *link_idx, int formula, int mission_num)
247271
node = CDR(formula);
248272
free_one_sexp(formula);
249273
while (node != -1) {
274+
init_link(Links[*link_idx], mission_num);
250275
node2 = CAR(node);
251-
Links[*link_idx].from = mission_num;
252276
Links[*link_idx].sexp = CAR(node2);
253-
Links[*link_idx].mission_branch_txt = NULL;
254-
Links[*link_idx].mission_branch_brief_anim = NULL;
255-
Links[*link_idx].mission_branch_brief_sound = NULL;
256277
sexp_mark_persistent(CAR(node2));
257278
free_one_sexp(node2);
258279
node3 = CADR(node2);
@@ -269,7 +290,7 @@ void stuff_link_with_formula(int *link_idx, int formula, int mission_num)
269290
}
270291

271292
} else if ( !stricmp( CTEXT(node3), "end-of-campaign") ) {
272-
Links[(*link_idx)++].to = -1;
293+
(*link_idx)++;
273294
Elements[mission_num].from_links++;
274295

275296
} else
@@ -292,7 +313,7 @@ void campaign_tree_view::construct_tree()
292313

293314
// initialize mission link counts
294315
for (i=0; i<Campaign.num_missions; i++) {
295-
Elements[i].from_links = Elements[i].to_links = 0;
316+
init_element(Elements[i]);
296317
}
297318

298319
// analyze branching sexps and build links from them.
@@ -753,14 +774,7 @@ int campaign_tree_view::add_link(int from, int to)
753774
return -1;
754775

755776
Campaign_tree_formp->load_tree(1);
756-
Links[Total_links].from = from;
757-
Links[Total_links].to = to;
758-
Links[Total_links].sexp = Locked_sexp_true;
759-
Links[Total_links].is_mission_loop = false;
760-
Links[Total_links].is_mission_fork = false;
761-
Links[Total_links].mission_branch_txt = NULL;
762-
Links[Total_links].mission_branch_brief_anim = NULL;
763-
Links[Total_links].mission_branch_brief_sound = NULL;
777+
init_link(Links[Total_links], from, to);
764778
Total_links++;
765779
if (from != to) {
766780
if (from >= 0)
@@ -964,7 +978,7 @@ BOOL campaign_tree_view::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffe
964978
}
965979
}
966980
967-
Elements[Campaign.num_missions].from_links = Elements[Campaign.num_missions].to_links = 0;
981+
init_element(Elements[Campaign.num_missions]);
968982
cm = &(Campaign.missions[Campaign.num_missions++]);
969983
cm->name = strdup(pData);
970984
cm->formula = Locked_sexp_true;
@@ -1062,7 +1076,7 @@ void campaign_tree_view::drop_mission(int m, CPoint point)
10621076
}
10631077
}
10641078

1065-
Elements[Campaign.num_missions].from_links = Elements[Campaign.num_missions].to_links = 0;
1079+
init_element(Elements[Campaign.num_missions]);
10661080
cm = &(Campaign.missions[Campaign.num_missions++]);
10671081
cm->name = strdup(name);
10681082
cm->formula = Locked_sexp_true;

fred2/campaigntreeview.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ extern int Sorted[MAX_CAMPAIGN_MISSIONS];
4343
extern campaign_tree_element Elements[MAX_CAMPAIGN_MISSIONS];
4444
extern campaign_tree_link Links[MAX_CAMPAIGN_TREE_LINKS];
4545

46+
extern void init_link(campaign_tree_link &link, int from = -1, int to = -1);
47+
extern void init_element(campaign_tree_element &element);
48+
4649
/////////////////////////////////////////////////////////////////////////////
4750
// campaign_tree_view view
4851

0 commit comments

Comments
 (0)