Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions code/missioneditor/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "mission/missionparse.h"
#include "iff_defs/iff_defs.h"
#include "jumpnode/jumpnode.h"
#include "mission/missioncampaign.h"
#include "object/object.h"
#include "object/waypoint.h"
#include "prop/prop.h"
Expand Down Expand Up @@ -318,6 +319,24 @@ SCP_string check_name_conflict(const char *entity_type, const char *name, int ex
return ""; // no error
}

int load_and_find_campaign_mission(const char *mission_filename)
{
if (!mission_filename[0])
return -1;

int idx = mission_campaign_find_mission(mission_filename);
if (idx < 0)
return -1;

if (Campaign.missions[idx].flags & CMISSION_FLAG_FRED_LOAD_PENDING)
{
read_mission_goal_list(idx);
Campaign.missions[idx].flags &= ~CMISSION_FLAG_FRED_LOAD_PENDING;
}

return idx;
}

void reassign_ship_slot(int from, int to, const FredShipSlotConfig& cfg, bool resort_obj_list)
{
Assertion(Fred_running, "reassign_ship_slot is FRED-only: it does not fix up game-context references like Player_ship or runtime Ai_info shipnums");
Expand Down
4 changes: 4 additions & 0 deletions code/missioneditor/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ bool set_single_player_start(int objnum);
// against the entity currently being renamed.
SCP_string check_name_conflict(const char *entity_type, const char *name, int exclude_ship = -1, int exclude_wing = -1, int exclude_waypoint_list = -1, int exclude_jump_node = -1);

// Resolve a mission filename to its index in Campaign.missions[], lazy-loading the mission's goal/event name lists from disk if the
// FRED_LOAD_PENDING flag is still set. Returns -1 if the mission isn't in the campaign.
int load_and_find_campaign_mission(const char *mission_filename);

struct FredShipSlotConfig
{
char (*fred_alt_names)[NAME_LENGTH + 1] = nullptr;
Expand Down
50 changes: 50 additions & 0 deletions fred2/campaigneditordlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
#include "cfile/cfile.h"
#include "FREDDoc.h"
#include "parse/parselo.h"
#include "mission/missioncampaign.h"
#include "mission/missiongoals.h"
#include "missioneditor/common.h"

#ifdef _DEBUG
#undef THIS_FILE
Expand Down Expand Up @@ -79,6 +81,54 @@ int campaign_editor::onRootDeleted(int formula_node)
void campaign_editor::onRootInserted(int old_formula, int new_formula) { insert_handler(old_formula, new_formula); }
void campaign_editor::onRootMoved(int node1, int node2, bool insert_before) { move_handler(node1, node2, insert_before); }

SCP_vector<SCP_string> campaign_editor::getMissionNames()
{
SCP_vector<SCP_string> list;
if (Cur_campaign_mission < 0)
return list;

// only list missions the player could have already played: the current mission and
// any mission at an earlier level in the campaign tree
for (int i = 0; i < Campaign.num_missions; i++)
{
if ((i == Cur_campaign_mission) || (Campaign.missions[i].level < Campaign.missions[Cur_campaign_mission].level))
list.emplace_back(Campaign.missions[i].name);
}

return list;
}

bool campaign_editor::hasDefaultMissionName()
{
return Cur_campaign_mission >= 0;
}

SCP_vector<SCP_string> campaign_editor::getMissionGoals(const SCP_string& reference_name)
{
SCP_vector<SCP_string> list;
int idx = load_and_find_campaign_mission(reference_name.c_str());
if (idx < 0)
return list;

for (const auto& goal : Campaign.missions[idx].goals)
list.emplace_back(goal.name);

return list;
}

SCP_vector<SCP_string> campaign_editor::getMissionEvents(const SCP_string& reference_name)
{
SCP_vector<SCP_string> list;
int idx = load_and_find_campaign_mission(reference_name.c_str());
if (idx < 0)
return list;

for (const auto& event : Campaign.missions[idx].events)
list.emplace_back(event.name);

return list;
}

campaign_editor::~campaign_editor()
{
}
Expand Down
6 changes: 6 additions & 0 deletions fred2/campaigneditordlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class campaign_editor : public CFormView, public SexpTreeEditorInterface
void onRootInserted(int old_formula, int new_formula) override;
void onRootMoved(int node1, int node2, bool insert_before) override;

SCP_vector<SCP_string> getMissionNames() override;
bool hasDefaultMissionName() override;

SCP_vector<SCP_string> getMissionGoals(const SCP_string& reference_name) override;
SCP_vector<SCP_string> getMissionEvents(const SCP_string& reference_name) override;

// Form Data
public:
void mission_selected(int num);
Expand Down
26 changes: 3 additions & 23 deletions qtfred/src/ui/dialogs/CampaignEditorDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <globalincs/globals.h>
#include "mission/missioncampaign.h"
#include "missioneditor/common.h"
#include "ui/widgets/sexp_tree_view.h"
#include "ui/widgets/SimpleListSelectDialog.h"
#include "ui/util/default_dir.h"
Expand Down Expand Up @@ -180,31 +181,10 @@ bool CampaignEditorDialog::hasDefaultMissionName()
return _model && !_model->getCampaignMissions().empty();
}

// Resolve a mission filename (as it appears in the sexp tree) to its index in the
// global Campaign.missions[] table that syncCampaignMissionList() mirrors from
// _model->getCampaignMissions(). Lazy-loads the goal/event list from disk if the
// FRED_LOAD_PENDING flag is still set. Returns -1 if the mission isn't in the
// campaign yet (e.g. the user is typing the name from scratch).
static int loadAndFindCampaignMission(const SCP_string& reference_name)
{
if (reference_name.empty()) {
return -1;
}
int idx = mission_campaign_find_mission(reference_name.c_str());
if (idx < 0) {
return -1;
}
if (Campaign.missions[idx].flags & CMISSION_FLAG_FRED_LOAD_PENDING) {
read_mission_goal_list(idx);
Campaign.missions[idx].flags &= ~CMISSION_FLAG_FRED_LOAD_PENDING;
}
return idx;
}

SCP_vector<SCP_string> CampaignEditorDialog::getMissionGoals(const SCP_string& reference_name)
{
SCP_vector<SCP_string> list;
const int idx = loadAndFindCampaignMission(reference_name);
const int idx = load_and_find_campaign_mission(reference_name.c_str());
if (idx < 0) {
return list;
}
Expand All @@ -217,7 +197,7 @@ SCP_vector<SCP_string> CampaignEditorDialog::getMissionGoals(const SCP_string& r
SCP_vector<SCP_string> CampaignEditorDialog::getMissionEvents(const SCP_string& reference_name)
{
SCP_vector<SCP_string> list;
const int idx = loadAndFindCampaignMission(reference_name);
const int idx = load_and_find_campaign_mission(reference_name.c_str());
if (idx < 0) {
return list;
}
Expand Down
Loading