1+ #include " DebriefingDialogModel.h"
2+ #include " missionui/missioncmdbrief.h" // TODO remove?
3+ #include " mission/missionparse.h" // TODO remove?
4+ #include " gamesnd/eventmusic.h"
5+ #include " sound/audiostr.h"
6+ #include < QMessageBox>
7+
8+ namespace fso ::fred::dialogs {
9+
10+ DebriefingDialogModel::DebriefingDialogModel (QObject* parent, EditorViewport* viewport)
11+ : AbstractDialogModel(parent, viewport)
12+ {
13+ initializeData ();
14+ }
15+
16+ bool DebriefingDialogModel::apply ()
17+ {
18+ stopSpeech ();
19+
20+ for (int i = 0 ; i < MAX_TVT_TEAMS; i++) {
21+ Debriefings[i] = _wipDebriefing[i];
22+ }
23+
24+ Mission_music[SCORE_DEBRIEFING_SUCCESS] = _successMusic;
25+ Mission_music[SCORE_DEBRIEFING_AVERAGE] = _averageMusic;
26+ Mission_music[SCORE_DEBRIEFING_FAILURE] = _failureMusic;
27+
28+ return true ;
29+ }
30+
31+ void DebriefingDialogModel::reject ()
32+ {
33+ stopSpeech ();
34+
35+ }
36+
37+ void DebriefingDialogModel::initializeData ()
38+ {
39+ initializeTeamList ();
40+
41+ // Make a working copy
42+ for (int i = 0 ; i < MAX_TVT_TEAMS; i++) {
43+ _wipDebriefing[i] = Debriefings[i];
44+ }
45+
46+ _successMusic = Mission_music[SCORE_DEBRIEFING_SUCCESS];
47+ _averageMusic = Mission_music[SCORE_DEBRIEFING_AVERAGE];
48+ _failureMusic = Mission_music[SCORE_DEBRIEFING_FAILURE];
49+
50+ _currentTeam = 0 ;
51+ _currentStage = 0 ;
52+ }
53+
54+ void DebriefingDialogModel::gotoPreviousStage ()
55+ {
56+ if (_currentStage <= 0 ) {
57+ _currentStage = 0 ;
58+ return ;
59+ }
60+
61+ stopSpeech ();
62+ _currentStage--;
63+ }
64+
65+ void DebriefingDialogModel::gotoNextStage ()
66+ {
67+ if (_currentStage >= MAX_DEBRIEF_STAGES - 1 ) {
68+ _currentStage = MAX_DEBRIEF_STAGES - 1 ;
69+ return ;
70+ }
71+
72+ if (_currentStage >= _wipDebriefing[_currentTeam].num_stages - 1 ) {
73+ _currentStage = _wipDebriefing[_currentTeam].num_stages - 1 ;
74+ return ;
75+ }
76+
77+ _currentStage++;
78+ stopSpeech ();
79+ }
80+
81+ void DebriefingDialogModel::addStage ()
82+ {
83+ stopSpeech ();
84+
85+ if (_wipDebriefing[_currentTeam].num_stages >= MAX_DEBRIEF_STAGES) {
86+ _wipDebriefing[_currentTeam].num_stages = MAX_DEBRIEF_STAGES;
87+ _currentStage = _wipDebriefing[_currentTeam].num_stages - 1 ;
88+ return ;
89+ }
90+
91+ _wipDebriefing[_currentTeam].num_stages ++;
92+ _currentStage = _wipDebriefing[_currentTeam].num_stages - 1 ;
93+ _wipDebriefing[_currentTeam].stages [_currentStage].text = " <Text here>" ;
94+ _wipDebriefing[_currentTeam].stages [_currentStage].recommendation_text = " <Recommendation text here>" ;
95+ strcpy_s (_wipDebriefing[_currentTeam].stages [_currentStage].voice , " none.wav" ); // Really? Seeding with none.wav is gross
96+ _wipDebriefing[_currentTeam].stages [_currentStage].formula = -1 ;
97+
98+ set_modified ();
99+ }
100+
101+ // copies the current stage as the next stage and then moves the rest of the stages over.
102+ void DebriefingDialogModel::insertStage ()
103+ {
104+ stopSpeech ();
105+
106+ if (_wipDebriefing[_currentTeam].num_stages >= MAX_DEBRIEF_STAGES) {
107+ _wipDebriefing[_currentTeam].num_stages = MAX_DEBRIEF_STAGES;
108+ set_modified ();
109+ return ;
110+ }
111+
112+ _wipDebriefing[_currentTeam].num_stages ++;
113+
114+ for (int i = _wipDebriefing[_currentTeam].num_stages - 1 ; i > _currentStage; i--) {
115+ _wipDebriefing[_currentTeam].stages [i] = _wipDebriefing[_currentTeam].stages [i - 1 ];
116+ }
117+
118+ // Future TODO: Add a QtFRED Option to clear the inserted stage instead of copying the current one.
119+
120+ set_modified ();
121+ }
122+
123+ void DebriefingDialogModel::deleteStage ()
124+ {
125+ stopSpeech ();
126+
127+ // Clear everything if we were on the last stage.
128+ if (_wipDebriefing[_currentTeam].num_stages <= 1 ) {
129+ _wipDebriefing[_currentTeam].num_stages = 0 ;
130+ _wipDebriefing[_currentTeam].stages [0 ].text .clear ();
131+ _wipDebriefing[_currentTeam].stages [0 ].recommendation_text .clear ();
132+ memset (_wipDebriefing[_currentTeam].stages [0 ].voice , 0 , CF_MAX_FILENAME_LENGTH);
133+ _wipDebriefing[_currentTeam].stages [0 ].formula = -1 ;
134+ set_modified ();
135+ return ;
136+ }
137+
138+ // copy the stages backwards until we get to the stage we're on
139+ for (int i = _currentStage; i + 1 < _wipDebriefing[_currentTeam].num_stages ; i++) {
140+ _wipDebriefing[_currentTeam].stages [i] = _wipDebriefing[_currentTeam].stages [i + 1 ];
141+ }
142+
143+ _wipDebriefing[_currentTeam].num_stages --;
144+
145+ // Clear the tail
146+ const int tail = _wipDebriefing[_currentTeam].num_stages ; // index of the old last element
147+ _wipDebriefing[_currentTeam].stages [tail].text .clear ();
148+ _wipDebriefing[_currentTeam].stages [tail].recommendation_text .clear ();
149+ std::memset (_wipDebriefing[_currentTeam].stages [tail].voice , 0 , CF_MAX_FILENAME_LENGTH);
150+ _wipDebriefing[_currentTeam].stages [tail].formula = -1 ;
151+
152+ // make sure that the current stage is valid.
153+ if (_wipDebriefing[_currentTeam].num_stages <= _currentStage) {
154+ _currentStage = _wipDebriefing[_currentTeam].num_stages - 1 ;
155+ }
156+
157+ set_modified ();
158+ }
159+
160+ void DebriefingDialogModel::testSpeech ()
161+ {
162+ // May cause unloading/reloading but it's just the mission editor
163+ // we don't need to keep all the waves loaded only to have to unload them
164+ // later anyway. This ensures we have one wave loaded and stopSpeech always unloads it
165+
166+ stopSpeech ();
167+
168+ _waveId = audiostream_open (_wipDebriefing[_currentTeam].stages [_currentStage].voice , ASF_EVENTMUSIC);
169+ audiostream_play (_waveId, 1 .0f , 0 );
170+ }
171+
172+ void DebriefingDialogModel::copyToOtherTeams ()
173+ {
174+ stopSpeech ();
175+
176+ for (int i = 0 ; i < MAX_TVT_TEAMS; i++) {
177+ if (i != _currentTeam) {
178+ _wipDebriefing[i] = _wipDebriefing[_currentTeam];
179+ }
180+ }
181+ set_modified ();
182+ }
183+
184+ const SCP_vector<std::pair<SCP_string, int >>& DebriefingDialogModel::getTeamList ()
185+ {
186+ return _teamList;
187+ }
188+
189+ bool DebriefingDialogModel::getMissionIsMultiTeam ()
190+ {
191+ return The_mission.game_type & MISSION_TYPE_MULTI_TEAMS;
192+ }
193+
194+ void DebriefingDialogModel::stopSpeech ()
195+ {
196+ if (_waveId >= -1 ) {
197+ audiostream_close_file (_waveId, false );
198+ _waveId = -1 ;
199+ }
200+ }
201+
202+ void DebriefingDialogModel::initializeTeamList ()
203+ {
204+ _teamList.clear ();
205+ for (auto & team : Mission_event_teams_tvt) {
206+ _teamList.emplace_back (team.first , team.second );
207+ }
208+ }
209+
210+ int DebriefingDialogModel::getCurrentTeam () const
211+ {
212+ return _currentTeam;
213+ }
214+
215+ void DebriefingDialogModel::setCurrentTeam (int teamIn)
216+ {
217+ modify (_currentTeam, teamIn);
218+ };
219+
220+ int DebriefingDialogModel::getCurrentStage () const
221+ {
222+ return _currentStage;
223+ }
224+
225+ int DebriefingDialogModel::getTotalStages ()
226+ {
227+ return _wipDebriefing[_currentTeam].num_stages ;
228+ }
229+
230+ SCP_string DebriefingDialogModel::getStageText ()
231+ {
232+ return _wipDebriefing[_currentTeam].stages [_currentStage].text ;
233+ }
234+
235+ void DebriefingDialogModel::setStageText (const SCP_string& text)
236+ {
237+ modify (_wipDebriefing[_currentTeam].stages [_currentStage].text , text);
238+ }
239+
240+ SCP_string DebriefingDialogModel::getRecommendationText ()
241+ {
242+ return _wipDebriefing[_currentTeam].stages [_currentStage].recommendation_text ;
243+ }
244+
245+ void DebriefingDialogModel::setRecommendationText (const SCP_string& text)
246+ {
247+ modify (_wipDebriefing[_currentTeam].stages [_currentStage].recommendation_text , text);
248+ }
249+
250+ SCP_string DebriefingDialogModel::getSpeechFilename ()
251+ {
252+ return _wipDebriefing[_currentTeam].stages [_currentStage].voice ;
253+ }
254+
255+ void DebriefingDialogModel::setSpeechFilename (const SCP_string& speechFilename)
256+ {
257+ strcpy_s (_wipDebriefing[_currentTeam].stages [_currentStage].voice , speechFilename.c_str ());
258+ set_modified ();
259+ }
260+
261+ int DebriefingDialogModel::getFormula () const
262+ {
263+ return _wipDebriefing[_currentTeam].stages [_currentStage].formula ;
264+ }
265+
266+ void DebriefingDialogModel::setFormula (int formula)
267+ {
268+ modify (_wipDebriefing[_currentTeam].stages [_currentStage].formula , formula);
269+ }
270+
271+ SCP_vector<SCP_string> DebriefingDialogModel::getMusicList ()
272+ {
273+ SCP_vector<SCP_string> music_list;
274+ music_list.emplace_back (" None" );
275+
276+ for (const auto & sm : Spooled_music) {
277+ music_list.emplace_back (sm.name );
278+ }
279+
280+ return music_list;
281+ }
282+
283+ int DebriefingDialogModel::getSuccessMusicTrack () const
284+ {
285+ return _successMusic;
286+ }
287+ void DebriefingDialogModel::setSuccessMusicTrack (int trackIndex)
288+ {
289+ modify (_successMusic, trackIndex);
290+ }
291+ int DebriefingDialogModel::getAverageMusicTrack () const
292+ {
293+ return _averageMusic;
294+ }
295+ void DebriefingDialogModel::setAverageMusicTrack (int trackIndex)
296+ {
297+ modify (_averageMusic, trackIndex);
298+ }
299+ int DebriefingDialogModel::getFailureMusicTrack () const
300+ {
301+ return _failureMusic;
302+ }
303+ void DebriefingDialogModel::setFailureMusicTrack (int trackIndex)
304+ {
305+ modify (_failureMusic, trackIndex);
306+ }
307+
308+ } // namespace fso::fred::dialogs
0 commit comments