1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2016 by Bertram (Valyria Tear)
4 //                         All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See https://www.gnu.org/copyleft/gpl.html for details.
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 #include "modes/map/map_dialogues/map_sprite_dialogue.h"
12 
13 #include "modes/map/map_dialogue_supervisor.h"
14 #include "modes/map/map_event_supervisor.h"
15 #include "modes/map/map_dialogues/map_dialogue_options.h"
16 #include "modes/map/map_sprites/map_sprite.h"
17 #include "modes/map/map_mode.h"
18 
19 #include "common/global/global.h"
20 
21 namespace vt_map
22 {
23 
24 namespace private_map
25 {
26 
SpriteDialogue()27 SpriteDialogue::SpriteDialogue() :
28     Dialogue(MapMode::CurrentInstance()->GetDialogueSupervisor()->GenerateDialogueID()),
29     _input_blocked(false),
30     _restore_state(true),
31     _dialogue_seen(false)
32 {
33     // Auto-registers the dialogue for later deletion handling.
34     MapMode::CurrentInstance()->GetDialogueSupervisor()->AddDialogue(this);
35 }
36 
SpriteDialogue(const std::string & dialogue_event_name)37 SpriteDialogue::SpriteDialogue(const std::string& dialogue_event_name) :
38     Dialogue(MapMode::CurrentInstance()->GetDialogueSupervisor()->GenerateDialogueID()),
39     _input_blocked(false),
40     _restore_state(true),
41     _event_name(dialogue_event_name)
42 {
43     // Check whether the dialogue as already been seen
44     _dialogue_seen = false;
45     if (_event_name.empty())
46         return;
47 
48     int32_t seen = vt_global::GlobalManager->GetGameEvents().GetEventValue("dialogues", _event_name);
49     if (seen > 0)
50         _dialogue_seen = true;
51 
52     // Auto-registers the dialogue for later deletion handling.
53     MapMode::CurrentInstance()->GetDialogueSupervisor()->AddDialogue(this);
54 }
55 
Create()56 SpriteDialogue* SpriteDialogue::Create()
57 {
58     // The object auto register to the object supervisor
59     // and will later handle deletion.
60     return new SpriteDialogue();
61 }
62 
Create(const std::string & dialogue_event_name)63 SpriteDialogue* SpriteDialogue::Create(const std::string& dialogue_event_name)
64 {
65     // The object auto register to the object supervisor
66     // and will later handle deletion.
67     return new SpriteDialogue(dialogue_event_name);
68 }
69 
SetAsSeen(bool seen)70 void SpriteDialogue::SetAsSeen(bool seen)
71 {
72     _dialogue_seen = seen;
73 
74     if (_event_name.empty())
75         return;
76 
77     // Stores the dialogue state in the save data
78     int32_t event_value = 0;
79     if (_dialogue_seen)
80         event_value = 1;
81 
82     vt_global::GlobalManager->GetGameEvents().SetEventValue("dialogues", _event_name, event_value);
83 }
84 
AddLine(const std::string & text,MapSprite * speaker)85 void SpriteDialogue::AddLine(const std::string &text, MapSprite *speaker)
86 {
87     AddLineTimedEvent(text, speaker,
88                       vt_common::DIALOGUE_NEXT_LINE, vt_common::DIALOGUE_NO_TIMER,
89                       std::string(), std::string(), std::string());
90 }
91 
AddLineEmote(const std::string & text,MapSprite * speaker,const std::string & emote_id)92 void SpriteDialogue::AddLineEmote(const std::string &text, MapSprite *speaker,
93                                   const std::string &emote_id)
94 {
95     AddLineTimedEvent(text, speaker,
96                       vt_common::DIALOGUE_NEXT_LINE, vt_common::DIALOGUE_NO_TIMER,
97                       std::string(), std::string(), emote_id);
98 }
99 
AddLine(const std::string & text,MapSprite * speaker,int32_t next_line)100 void SpriteDialogue::AddLine(const std::string &text, MapSprite *speaker, int32_t next_line)
101 {
102     AddLineTimedEvent(text, speaker,
103                       next_line, vt_common::DIALOGUE_NO_TIMER,
104                       std::string(), std::string(), std::string());
105 }
106 
AddLineTimed(const std::string & text,MapSprite * speaker,uint32_t display_time)107 void SpriteDialogue::AddLineTimed(const std::string &text, MapSprite *speaker, uint32_t display_time)
108 {
109     AddLineTimedEvent(text, speaker,
110                       vt_common::DIALOGUE_NEXT_LINE, display_time,
111                       std::string(), std::string(), std::string());
112 }
113 
AddLineTimed(const std::string & text,MapSprite * speaker,int32_t next_line,uint32_t display_time)114 void SpriteDialogue::AddLineTimed(const std::string &text, MapSprite *speaker, int32_t next_line, uint32_t display_time)
115 {
116     AddLineTimedEvent(text, speaker,
117                       next_line, display_time,
118                       std::string(), std::string(), std::string());
119 }
120 
AddLineEvent(const std::string & text,MapSprite * speaker,const std::string & begin_event_id,const std::string & end_event_id)121 void SpriteDialogue::AddLineEvent(const std::string &text, MapSprite *speaker,
122                                   const std::string &begin_event_id, const std::string &end_event_id)
123 {
124     AddLineTimedEvent(text, speaker,
125                       vt_common::DIALOGUE_NEXT_LINE, vt_common::DIALOGUE_NO_TIMER,
126                       begin_event_id, end_event_id, std::string());
127 }
128 
AddLineEventEmote(const std::string & text,MapSprite * speaker,const std::string & begin_event_id,const std::string & end_event_id,const std::string & emote_id)129 void SpriteDialogue::AddLineEventEmote(const std::string &text,
130                                        MapSprite *speaker,
131                                        const std::string &begin_event_id,
132                                        const std::string &end_event_id,
133                                        const std::string &emote_id)
134 {
135     AddLineTimedEvent(text, speaker,
136                       vt_common::DIALOGUE_NEXT_LINE, vt_common::DIALOGUE_NO_TIMER,
137                       begin_event_id, end_event_id, emote_id);
138 }
139 
AddLineEvent(const std::string & text,MapSprite * speaker,int32_t next_line,const std::string & begin_event_id,const std::string & end_event_id)140 void SpriteDialogue::AddLineEvent(const std::string &text, MapSprite *speaker, int32_t next_line,
141                                   const std::string &begin_event_id, const std::string &end_event_id)
142 {
143     AddLineTimedEvent(text, speaker,
144                       next_line, vt_common::DIALOGUE_NO_TIMER,
145                       begin_event_id, end_event_id, std::string());
146 }
147 
AddLineTimedEvent(const std::string & text,MapSprite * speaker,uint32_t display_time,const std::string & begin_event_id,const std::string & end_event_id)148 void SpriteDialogue::AddLineTimedEvent(const std::string &text, MapSprite *speaker, uint32_t display_time,
149                                        const std::string &begin_event_id, const std::string &end_event_id)
150 {
151     AddLineTimedEvent(text, speaker,
152                       vt_common::DIALOGUE_NEXT_LINE, display_time,
153                       begin_event_id, end_event_id, std::string());
154 }
155 
AddLineTimedEvent(const std::string & text,MapSprite * speaker,int32_t next_line,uint32_t display_time,const std::string & begin_event_id,const std::string & end_event_id,const std::string & emote_id)156 void SpriteDialogue::AddLineTimedEvent(const std::string &text, MapSprite *speaker,
157                                        int32_t next_line, uint32_t display_time,
158                                        const std::string &begin_event_id, const std::string &end_event_id,
159                                        const std::string& emote_id)
160 {
161     Dialogue::AddLineTimed(text, next_line, display_time);
162     _speakers.push_back(speaker);
163     _begin_events.push_back(begin_event_id);
164     _end_events.push_back(end_event_id);
165     _emote_events.push_back(emote_id);
166 }
167 
AddOption(const std::string & text)168 void SpriteDialogue::AddOption(const std::string &text)
169 {
170     AddOptionEvent(text, vt_common::DIALOGUE_NEXT_LINE, std::string());
171 }
172 
AddOption(const std::string & text,int32_t next_line)173 void SpriteDialogue::AddOption(const std::string &text, int32_t next_line)
174 {
175     AddOptionEvent(text, next_line, std::string());
176 }
177 
AddOptionEvent(const std::string & text,const std::string & event_id)178 void SpriteDialogue::AddOptionEvent(const std::string &text, const std::string &event_id)
179 {
180     AddOptionEvent(text, vt_common::DIALOGUE_NEXT_LINE, event_id);
181 }
182 
AddOptionEvent(const std::string & text,int32_t next_line,const std::string & event_id)183 void SpriteDialogue::AddOptionEvent(const std::string &text, int32_t next_line, const std::string &event_id)
184 {
185     if(_line_count == 0) {
186         IF_PRINT_WARNING(MAP_DEBUG) << "Attempted to add an option to a dialogue with no lines" << std::endl;
187         return;
188     }
189 
190     uint32_t current_line = _line_count - 1;
191 
192     // If the line the options will be added to currently has no options, create a new instance of the MapDialogueOptions class to store the options in.
193     if(_options[current_line] == nullptr) {
194         _options[current_line] = new MapDialogueOptions();
195     }
196 
197     MapDialogueOptions *options = dynamic_cast<MapDialogueOptions *>(_options[current_line]);
198     options->AddOptionEvent(text, next_line, event_id);
199 }
200 
Validate()201 bool SpriteDialogue::Validate()
202 {
203     if(Dialogue::Validate() == false) {
204         // The CommonDialogue::Validate() call will print the appropriate warnings
205         // if debugging is enabled (common code debugging that is)
206         return false;
207     }
208 
209     // Construct containers that hold all unique sprite and event ids for this dialogue
210     std::set<std::string> event_ids;
211     for(uint32_t i = 0; i < _line_count; i++) {
212         event_ids.insert(_end_events[i]);
213     }
214 
215     for(std::set<std::string>::iterator it = event_ids.begin(); it != event_ids.end(); ++it) {
216         if((*it).empty())
217             continue;
218 
219         if(MapMode::CurrentInstance()->GetEventSupervisor()->GetEvent(*it) == nullptr) {
220             IF_PRINT_WARNING(MAP_DEBUG) << "Validation failed for dialogue #" << _dialogue_id
221                                         << ": dialogue referenced invalid event with id: " << *it << std::endl;
222             return false;
223         }
224     }
225 
226     return true;
227 }
228 
229 } // namespace private_map
230 
231 } // namespace vt_map
232