@@ -31,8 +31,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
3131#include " ignore_unused_variable_warning.h"
3232#include " misc_buttons.h"
3333#include " objiter.h"
34+ #include " msgfile.h"
35+ #include " U7obj.h"
36+ #include " utils.h"
37+ #include " data/exult_bg_flx.h"
38+ #include " data/exult_si_flx.h"
39+ #include " databuf.h"
3440
3541#include < algorithm>
42+ #include < cctype>
43+ #include < charconv>
44+
45+ std::unique_ptr<Text_msg_file_reader> Gump::gump_area_info;
3646
3747/*
3848 * Create a gump.
@@ -126,9 +136,117 @@ void Gump::set_pos(int newx, int newy) { // Set new spot on screen.
126136 * Sets object area and creates checkmark button
127137 */
128138
129- void Gump::set_object_area (const TileRect& area, int checkx, int checky) {
139+ static bool read_int_and_advance (std::string_view& line, int & val)
140+ {
141+ // Remove whitspace from start
142+ while (line.size () && std::isspace (line.front ())) {
143+ line.remove_prefix (1 );
144+ }
145+
146+
147+ if (!line.size ()) {
148+ return false ;
149+ }
150+
151+ // find the comma or end
152+ size_t comma = line.find (' ,' , 0 );
153+ if (comma == line.npos ) {
154+ comma = line.size ();
155+ }
156+ auto sub = line.substr (0 , comma );
157+
158+ // remove white space at end of subsctring befor comma
159+ while (sub.size () && std::isspace (sub.back ())) {
160+ sub.remove_suffix (1 );
161+ }
162+
163+ if (!sub.size ()) {
164+ return false ;
165+ }
166+
167+ auto res
168+ = std::from_chars (sub.data (), sub.data () + sub.size (), val, 10 );
169+ if (res.ptr != sub.data () + sub.size ()) {
170+ return false ;
171+ }
172+
173+ if (comma+1 >= line.size ()) {
174+ line = std::string_view ();
175+ } else {
176+ line = line.substr (comma+1 );
177+ }
178+
179+ return true ;
180+ }
181+
182+ void Gump::set_object_area (
183+ TileRect area, int checkx, int checky, bool set_check) {
184+
185+ if (!gump_area_info) {
186+ File_spec flx;
187+ if (GAME_BG) {
188+ flx = File_spec (
189+ BUNDLE_CHECK (BUNDLE_EXULT_BG_FLX, EXULT_BG_FLX),
190+ EXULT_BG_FLX_GUMP_AREA_INFO_TXT);
191+ }
192+ else if (GAME_SI) {
193+ flx = File_spec (
194+ BUNDLE_CHECK (BUNDLE_EXULT_SI_FLX, EXULT_SI_FLX),
195+ EXULT_SI_FLX_GUMP_AREA_INFO_TXT);
196+ }
197+
198+
199+ IExultDataSource datasource (
200+ flx, GUMP_AREA_INFO, PATCH_GUMP_AREA_INFO,0 );
201+ gump_area_info = std::make_unique<Text_msg_file_reader>(datasource);
202+
203+ }
204+
205+ // if we sucesfully read it try to use it
206+ if (gump_area_info && get_shapenum () >= 0 && get_shapefile ()==SF_GUMPS_VGA)
207+ {
208+ auto section = gump_area_info->get_global_section ();
209+ if (size_t (get_shapenum ()) < section.size ())
210+ {
211+ auto sv = section[(get_shapenum ())];
212+ if (sv.size ())
213+ {
214+ // Read 6 ints
215+ int vals[6 ];
216+ bool success = true ;
217+
218+ for (int &v : vals)
219+ {
220+ if (!(success = read_int_and_advance (sv, v))) {
221+ break ;
222+ }
223+
224+ }
225+
226+ // succeeded in parsing line, so update the values
227+ if (success)
228+ {
229+ area.x = vals[0 ];
230+ area.y = vals[1 ];
231+ area.w = vals[2 ];
232+ area.h = vals[3 ];
233+ checkx = vals[4 ];
234+ checky = vals[5 ];
235+
236+ }
237+ else
238+ {
239+ std::cerr << " Failed to parse line in "
240+ " gump_area_info.txt for gump "
241+ << get_shapenum () << std::endl;
242+ }
243+ }
244+ }
245+
246+ }
130247 object_area = area;
131- if (std::none_of (elems.begin (), elems.end (), [](auto elem) -> bool {
248+ if (set_check && std::none_of (
249+ elems.begin (), elems.end (), [](auto elem) -> bool {
132250 return dynamic_cast <Checkmark_button*>(elem) != nullptr ;
133251 })) {
134252 checkx += 16 ;
0 commit comments