Pol  Revision:cb584c9
UoConvertMain.cpp
Go to the documentation of this file.
1 #include "UoConvertMain.h"
2 
3 #include <stdio.h>
4 #include <string.h>
5 #include <string>
6 
7 #include "../clib/Program/ProgramMain.h"
8 #include "../clib/cfgelem.h"
9 #include "../clib/cfgfile.h"
10 #include "../clib/fileutil.h"
11 #include "../clib/logfacility.h"
12 #include "../clib/passert.h"
13 #include "../clib/rawtypes.h"
14 #include "../clib/stlutil.h"
15 #include "../clib/timer.h"
16 #include "../plib/mapcell.h"
17 #include "../plib/mapfunc.h"
18 #include "../plib/mapshape.h"
19 #include "../plib/mapsolid.h"
20 #include "../plib/maptile.h"
21 #include "../plib/mapwriter.h"
22 #include "../plib/realmdescriptor.h"
23 #include "../plib/systemstate.h"
24 #include "../plib/uopreader/uop.h"
25 #include "../plib/uopreader/uophash.h"
26 #include "../pol/clidata.h"
27 #include "../pol/objtype.h"
28 #include "../pol/polfile.h"
29 #include "../pol/udatfile.h"
30 #include "../pol/uofile.h"
31 #include "../pol/uofilei.h"
32 #include "../pol/ustruct.h"
33 
34 
35 namespace Pol
36 {
37 namespace UoConvert
38 {
39 using namespace std;
40 using namespace Pol::Core;
41 using namespace Pol::Plib;
42 
44 
45 
47 
48 UoConvertMain::UoConvertMain() : Pol::Clib::ProgramMain() {}
51 
53 {
54  ERROR_PRINT << "Usage:\n"
55  << " \n"
56  << " UOCONVERT command [options ...]\n"
57  << " \n"
58  << " Commands: \n"
59  << " map {uodata=Dir} {maxtileid=0x3FFF/0x7FFF} {realm=realmname} {width=Width}"
60  << " {height=Height} {mapid=0} {readuop=1} {x=X} {y=Y}\n"
61  << " statics {uodata=Dir} {maxtileid=0x3FFF/0x7FFF} {realm=realmname}\n"
62  << " maptile {uodata=Dir} {maxtileid=0x3FFF/0x7FFF} {realm=realmname}\n"
63  << " multis {uodata=Dir} {maxtileid=0x3FFF/0x7FFF}\n"
64  << " tiles {uodata=Dir} {maxtileid=0x3FFF/0x7FFF}\n"
65  << " landtiles {uodata=Dir} {maxtileid=0x3FFF/0x7FFF}\n";
66 }
67 
68 using namespace Core;
69 using namespace Plib;
70 
73 
74 std::set<unsigned int> HouseTypes;
75 std::set<unsigned int> BoatTypes;
76 std::set<unsigned int> StairTypes;
77 std::set<unsigned int> MountTypes;
78 
79 void create_map( const std::string& realm, unsigned short width, unsigned short height );
80 void update_map( const std::string& realm, unsigned short x, unsigned short y );
81 
82 void create_multis_cfg();
83 void create_tiles_cfg();
85 void create_maptile( const std::string& realmname );
86 
88 {
89  for ( unsigned blocking = 0; blocking <= 1; ++blocking )
90  {
91  for ( unsigned platform = 0; platform <= 1; ++platform )
92  {
93  for ( unsigned walk = 0; walk <= 1; ++walk )
94  {
95  for ( unsigned wall = 0; wall <= 1; ++wall )
96  {
97  for ( unsigned half = 0; half <= 1; ++half )
98  {
99  for ( unsigned floor = 0; floor <= 1; ++floor )
100  {
101  unsigned flags = 0;
102  if ( blocking )
104  if ( platform )
106  if ( walk )
108  if ( wall )
110  if ( half )
112  if ( floor )
114 
115  unsigned int polflags = Plib::polflags_from_tileflags(
116  0x4000, flags, cfg_use_no_shoot, cfg_LOS_through_windows );
117  unsigned moveland = ( polflags & Plib::FLAG::MOVELAND ) ? 1 : 0;
118  INFO_PRINT.Format( "{} {} {} {} {} {}: {}\n" )
119  << blocking << platform << walk << wall << half << floor << moveland;
120  }
121  }
122  }
123  }
124  }
125  }
126 }
127 
128 unsigned char polmap_flags_from_landtile( unsigned short landtile )
129 {
130  unsigned int uoflags = landtile_uoflags( landtile );
131 
132  unsigned int polflags =
133  Plib::polflags_from_tileflags( landtile, uoflags, cfg_use_no_shoot, cfg_LOS_through_windows );
134  return static_cast<unsigned char>( polflags );
135 }
136 
137 
138 void create_maptile( const std::string& realmname )
139 {
140  Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realmname );
141  uo_map_height = static_cast<unsigned short>( descriptor.height );
142  uo_map_width = static_cast<unsigned short>( descriptor.width );
143 
144  INFO_PRINT << "Creating maptile file.\n"
145  << " Realm: " << realmname << "\n"
146  << " Map ID: " << descriptor.uomapid << "\n"
147  << " Use Dif files: " << ( descriptor.uodif ? "Yes" : "No" ) << "\n"
148  << " Size: " << uo_map_width << "x" << uo_map_height << "\n";
149 
150  auto writer = new Plib::MapWriter();
151  writer->OpenExistingFiles( realmname );
152 
153  for ( unsigned short y_base = 0; y_base < uo_map_height; y_base += Plib::MAPTILE_CHUNK )
154  {
155  for ( unsigned short x_base = 0; x_base < uo_map_width; x_base += Plib::MAPTILE_CHUNK )
156  {
157  for ( unsigned short x_add = 0; x_add < Plib::MAPTILE_CHUNK; ++x_add )
158  {
159  for ( unsigned short y_add = 0; y_add < Plib::MAPTILE_CHUNK; ++y_add )
160  {
161  unsigned short x = x_base + x_add;
162  unsigned short y = y_base + y_add;
163 
164  short z;
166 
167  safe_getmapinfo( x, y, &z, &mi );
168 
169  if ( mi.landtile > 0x3FFF )
170  INFO_PRINT.Format( "Tile 0x{:X} at ({},{},{}) is an invalid ID!\n" )
171  << mi.landtile << x << y << z;
172 
173  // for water, don't average with surrounding tiles.
175  z = mi.z;
176 
177  Plib::MAPTILE_CELL cell;
178  cell.landtile = mi.landtile;
179  cell.z = static_cast<signed char>( z );
180  writer->SetMapTile( x, y, cell );
181  }
182  }
183  }
184  INFO_PRINT << "\rConverting: " << y_base * 100 / uo_map_height << "%";
185  }
186  writer->Flush();
187  delete writer;
188  INFO_PRINT << "\rConversion complete.\n";
189 }
190 
192 {
193 public:
194  bool operator()( const StaticRec& a, const StaticRec& b )
195  {
196  return ( a.z < b.z ) || ( ( a.z == b.z && a.height < b.height ) );
197  }
198 };
199 
200 bool flags_match( unsigned int f1, unsigned int f2, unsigned char bits_compare )
201 {
202  return ( f1 & bits_compare ) == ( f2 & bits_compare );
203 }
204 
205 bool otherflags_match( unsigned char f1, unsigned char f2, unsigned char bits_exclude )
206 {
207  return ( f1 & ~bits_exclude ) == ( f2 & ~bits_exclude );
208 }
209 
210 bool differby_exactly( unsigned char f1, unsigned char f2, unsigned char bits )
211 {
212  return ( ( f1 ^ f2 ) == bits );
213 }
214 
215 void ProcessSolidBlock( unsigned short x_base, unsigned short y_base, MapWriter& mapwriter );
216 
217 unsigned empty = 0, nonempty = 0;
218 unsigned total_statics = 0;
219 unsigned with_more_solids = 0;
220 
221 void update_map( const std::string& realm, unsigned short x, unsigned short y )
222 {
223  auto mapwriter = new MapWriter();
224  mapwriter->OpenExistingFiles( realm );
225  rawmapfullread();
227  unsigned short x_base = x / SOLIDX_X_SIZE * SOLIDX_X_SIZE;
228  unsigned short y_base = y / SOLIDX_Y_SIZE * SOLIDX_Y_SIZE;
229 
230  ProcessSolidBlock( x_base, y_base, *mapwriter );
231  delete mapwriter;
232  INFO_PRINT << "empty=" << empty << ", nonempty=" << nonempty << "\n"
233  << "with more_solids: " << with_more_solids << "\n"
234  << "total statics=" << total_statics << "\n";
235 }
236 
237 void create_map( const std::string& realm, unsigned short width, unsigned short height )
238 {
239  auto mapwriter = new MapWriter();
240  INFO_PRINT << "Creating map base and solids files.\n"
241  << " Realm: " << realm << "\n"
242  << " Map ID: " << uo_mapid << "\n"
243  << " Reading UOP file: " << ( uo_readuop ? "Yes" : "No" ) << "\n"
244  << " Use Dif files: " << ( uo_usedif ? "Yes" : "No" ) << "\n"
245  << " Size: " << uo_map_width << "x" << uo_map_height << "\n"
246  << "Initializing files: ";
247  mapwriter->CreateNewFiles( realm, width, height );
248  INFO_PRINT << "Done.\n";
249  Tools::Timer<> timer;
250  rawmapfullread();
252  INFO_PRINT << " Reading mapfiles time: " << timer.ellapsed() << " ms.\n";
253  for ( unsigned short y_base = 0; y_base < height; y_base += SOLIDX_Y_SIZE )
254  {
255  for ( unsigned short x_base = 0; x_base < width; x_base += SOLIDX_X_SIZE )
256  {
257  ProcessSolidBlock( x_base, y_base, *mapwriter );
258  }
259  INFO_PRINT << "\rConverting: " << y_base * 100 / height << "%";
260  }
261  timer.stop();
262 
263  mapwriter->WriteConfigFile();
264  delete mapwriter;
265 
266  INFO_PRINT << "\rConversion complete. \n"
267  << "Conversion details:\n"
268  << " Total blocks: " << empty + nonempty << "\n"
269  << " Blocks with solids: " << nonempty << " ("
270  << ( nonempty * 100 / ( empty + nonempty ) ) << "%)"
271  << "\n"
272  << " Blocks without solids: " << empty << " ("
273  << ( empty * 100 / ( empty + nonempty ) ) << "%)"
274  << "\n"
275  << " Locations with solids: " << with_more_solids << "\n"
276  << " Total number of solids: " << total_statics << "\n"
277  << " Elapsed time: " << timer.ellapsed() << " ms.\n";
278 }
279 
281 {
282  return ( mi.landtile == 0x2 );
283 }
284 
286 {
287  return ( mi.landtile == 0x7ec || mi.landtile == 0x7ed || mi.landtile == 0x7ee ||
288  mi.landtile == 0x7ef || mi.landtile == 0x7f0 || mi.landtile == 0x7f1 ||
289  mi.landtile == 0x834 || mi.landtile == 0x835 || mi.landtile == 0x836 ||
290  mi.landtile == 0x837 || mi.landtile == 0x838 || mi.landtile == 0x839 ||
291  mi.landtile == 0x1d3 || mi.landtile == 0x1d4 || mi.landtile == 0x1d5 ||
292  mi.landtile == 0x1d6 || mi.landtile == 0x1d7 || mi.landtile == 0x1d8 ||
293  mi.landtile == 0x1d9 || mi.landtile == 0x1da );
294 }
295 
297 {
298  return ( mi.landtile == 0x1db || // shadows above caves
299  mi.landtile == 0x1ae || // more shadows above caves
300  mi.landtile == 0x1af || mi.landtile == 0x1b0 || mi.landtile == 0x1b1 ||
301  mi.landtile == 0x1b2 || mi.landtile == 0x1b3 || mi.landtile == 0x1b4 ||
302  mi.landtile == 0x1b5 );
303 }
304 
305 short get_lowestadjacentz( unsigned short x, unsigned short y, short z )
306 {
307  USTRUCT_MAPINFO mi;
308  short z0;
309  short lowest_z = z;
310  bool cave_override = false;
311 
312  if ( ( x - 1 >= 0 ) && ( y - 1 >= 0 ) )
313  {
314  safe_getmapinfo( x - 1, y - 1, &z0, &mi );
315 
316  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
317  z0 = z;
318 
319  if ( is_no_draw( mi ) )
320  cave_override = true;
321 
322  if ( z0 < lowest_z )
323  {
324  lowest_z = z0;
325  }
326  }
327 
328  if ( x - 1 >= 0 )
329  {
330  safe_getmapinfo( x - 1, y, &z0, &mi );
331 
332  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
333  z0 = z;
334 
335  if ( is_no_draw( mi ) )
336  cave_override = true;
337 
338  if ( z0 < lowest_z )
339  {
340  lowest_z = z0;
341  }
342  }
343 
344  if ( ( x - 1 >= 0 ) && ( y + 1 < uo_map_height ) )
345  {
346  safe_getmapinfo( x - 1, y + 1, &z0, &mi );
347 
348  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
349  z0 = z;
350 
351  if ( is_no_draw( mi ) )
352  cave_override = true;
353 
354  if ( z0 < lowest_z )
355  {
356  lowest_z = z0;
357  }
358  }
359 
360  if ( y - 1 >= 0 )
361  {
362  safe_getmapinfo( x, y - 1, &z0, &mi );
363 
364  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
365  z0 = z;
366 
367  if ( is_no_draw( mi ) )
368  cave_override = true;
369 
370  if ( z0 < lowest_z )
371  {
372  lowest_z = z0;
373  }
374  }
375 
376  if ( ( y - 1 >= 0 ) && ( x + 1 < uo_map_width ) )
377  {
378  safe_getmapinfo( x + 1, y - 1, &z0, &mi );
379 
380  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
381  z0 = z;
382 
383  if ( is_no_draw( mi ) )
384  cave_override = true;
385 
386  if ( z0 < lowest_z )
387  {
388  lowest_z = z0;
389  }
390  }
391 
392  if ( x + 1 < uo_map_width )
393  {
394  safe_getmapinfo( x + 1, y, &z0, &mi );
395 
396  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
397  z0 = z;
398 
399  if ( is_no_draw( mi ) )
400  cave_override = true;
401 
402  if ( z0 < lowest_z )
403  {
404  lowest_z = z0;
405  }
406  }
407 
408  if ( ( x + 1 < uo_map_width ) && ( y + 1 < uo_map_height ) )
409  {
410  safe_getmapinfo( x + 1, y + 1, &z0, &mi );
411 
412  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
413  z0 = z;
414 
415  if ( is_no_draw( mi ) )
416  cave_override = true;
417 
418  if ( z0 < lowest_z )
419  {
420  lowest_z = z0;
421  }
422  }
423 
424  if ( y + 1 < uo_map_height )
425  {
426  safe_getmapinfo( x, y + 1, &z0, &mi );
427 
428  if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
429  z0 = z;
430 
431  if ( is_no_draw( mi ) )
432  cave_override = true;
433 
434  if ( z0 < lowest_z )
435  {
436  lowest_z = z0;
437  }
438  }
439 
440  if ( cave_override )
441  return z;
442  else
443  return lowest_z;
444 }
445 
446 void ProcessSolidBlock( unsigned short x_base, unsigned short y_base, MapWriter& mapwriter )
447 {
448  unsigned int idx2_offset = 0;
449  SOLIDX2_ELEM idx2_elem;
450  memset( &idx2_elem, 0, sizeof idx2_elem );
451  idx2_elem.baseindex = mapwriter.NextSolidIndex();
452 
453  unsigned short x_add_max = SOLIDX_X_SIZE, y_add_max = SOLIDX_Y_SIZE;
454  if ( x_base + x_add_max > uo_map_width )
455  x_add_max = uo_map_width - x_base;
456  if ( y_base + y_add_max > uo_map_height )
457  y_add_max = uo_map_height - y_base;
458 
459  for ( unsigned short x_add = 0; x_add < x_add_max; ++x_add )
460  {
461  for ( unsigned short y_add = 0; y_add < y_add_max; ++y_add )
462  {
463  unsigned short x = x_base + x_add;
464  unsigned short y = y_base + y_add;
465 
466  StaticList statics;
467 
468  // read the map, and treat it like a static.
469  short z;
470  USTRUCT_MAPINFO mi;
471 
472  safe_getmapinfo( x, y, &z, &mi );
473 
474  if ( mi.landtile > 0x3FFF )
475  INFO_PRINT.Format( "Tile 0x{:X} at ({},{},{}) is an invalid ID!\n" )
476  << mi.landtile << x << y << z;
477 
478  // for water, don't average with surrounding tiles.
480  z = mi.z;
481  short low_z = get_lowestadjacentz( x, y, z );
482 
483  short lt_height = z - low_z;
484  z = low_z;
485 
486  if ( mi.landtile > 0x3FFF )
487  INFO_PRINT.Format( "Tile 0x{:X} at ({},{},{}) is an invalid ID!\n" )
488  << mi.landtile << x << y << z;
489 
490  unsigned int lt_flags = landtile_uoflags( mi.landtile );
491  if ( ~lt_flags & USTRUCT_TILE::FLAG_BLOCKING )
492  { // this seems to be the default.
493  lt_flags |= USTRUCT_TILE::FLAG_PLATFORM;
494  }
495  lt_flags |=
496  USTRUCT_TILE::FLAG_NO_SHOOT; // added to make sure people using noshoot will have shapes
497  // generated by this tile in future block LOS, shouldn't
498  // affect people using old LOS method one way or another.
499  lt_flags |= USTRUCT_TILE::FLAG_FLOOR;
500  lt_flags |= USTRUCT_TILE::FLAG_HALF_HEIGHT; // the entire map is this way
501 
502  if ( lt_flags & USTRUCT_TILE::FLAG_WALL )
503  lt_height = 20;
504 
505  readstatics( statics, x, y,
506  USTRUCT_TILE::FLAG_BLOCKING | USTRUCT_TILE::FLAG_PLATFORM |
509  // USTRUCT_TILE::FLAG__WALK
510  );
511 
512  for ( unsigned i = 0; i < statics.size(); ++i )
513  {
514  StaticRec srec = statics[i];
515 
516  unsigned int polflags = polflags_from_tileflags( srec.graphic, srec.flags, cfg_use_no_shoot,
517  cfg_LOS_through_windows );
518 
519  if ( ( ~polflags & FLAG::MOVELAND ) && ( ~polflags & FLAG::MOVESEA ) &&
520  ( ~polflags & FLAG::BLOCKSIGHT ) && ( ~polflags & FLAG::BLOCKING ) &&
521  ( ~polflags & FLAG::OVERFLIGHT ) )
522  {
523  // remove it. we'll re-sort later.
524  statics.erase( statics.begin() + i );
525  --i; // do-over
526  }
527  if ( ( ~srec.flags & USTRUCT_TILE::FLAG_BLOCKING ) &&
528  ( ~srec.flags & USTRUCT_TILE::FLAG_PLATFORM ) &&
530  ( ~srec.flags & USTRUCT_TILE::FLAG_LIQUID ) &&
531  ( ~srec.flags & USTRUCT_TILE::FLAG_HOVEROVER ) )
532  /*(~srec.flags & USTRUCT_TILE::FLAG__WALK)*/
533  {
534  // remove it. we'll re-sort later.
535  statics.erase( statics.begin() + i );
536  --i; // do-over
537  }
538  }
539 
540  bool addMap = true;
541 
542  for ( const auto& srec : statics )
543  {
544  // Look for water tiles. If there are any, discard the map (which is usually at -15 anyway)
545  if ( z + lt_height <= srec.z &&
546  ( ( srec.z - ( z + lt_height ) ) <=
547  10 ) && // only where the map is below or same Z as the static
548  srec.graphic >= 0x1796 &&
549  srec.graphic <= 0x17B2 ) // FIXME hardcoded
550  {
551  // arr, there be water here
552  addMap = false;
553  }
554 
555  // if there's a static on top of one of these "wall" landtiles, make it override.
556  if ( ( lt_flags & USTRUCT_TILE::FLAG_WALL ) && // wall?
557  z <= srec.z && srec.z - z <= lt_height )
558  {
559  lt_height = srec.z - z;
560  }
561  }
562  // shadows above caves
563  if ( is_cave_shadow( mi ) && !statics.empty() )
564  {
565  addMap = false;
566  }
567 
568 
569  // If the map is a NODRAW tile, and there are statics, discard the map tile
570  if ( mi.landtile == 2 && !statics.empty() )
571  addMap = false;
572 
573  if ( addMap )
574  statics.push_back( StaticRec( 0, static_cast<signed char>( z ), lt_flags,
575  static_cast<char>( lt_height ) ) );
576 
577  sort( statics.begin(), statics.end(), StaticsByZ() );
578  reverse( statics.begin(), statics.end() );
579 
580  std::vector<MapShape> shapes;
581 
582  // try to consolidate like shapes, and discard ones we don't care about.
583  while ( !statics.empty() )
584  {
585  StaticRec srec = statics.back();
586  statics.pop_back();
587 
588  unsigned int polflags = polflags_from_tileflags( srec.graphic, srec.flags, cfg_use_no_shoot,
589  cfg_LOS_through_windows );
590  if ( ( ~polflags & FLAG::MOVELAND ) && ( ~polflags & FLAG::MOVESEA ) &&
591  ( ~polflags & FLAG::BLOCKSIGHT ) && ( ~polflags & FLAG::BLOCKING ) &&
592  ( ~polflags & FLAG::OVERFLIGHT ) )
593  {
594  passert_always( 0 );
595  continue;
596  }
597  if ( ( ~srec.flags & USTRUCT_TILE::FLAG_BLOCKING ) &&
598  ( ~srec.flags & USTRUCT_TILE::FLAG_PLATFORM ) &&
600  ( ~srec.flags & USTRUCT_TILE::FLAG_LIQUID ) &&
601  ( ~srec.flags & USTRUCT_TILE::FLAG_HOVEROVER ) )
602  /*(~srec.flags & USTRUCT_TILE::FLAG__WALK)*/
603  {
604  passert_always( 0 );
605  continue;
606  }
607 
608  if ( shapes.empty() )
609  {
610  // this, whatever it is, is the map base.
611  // TODO: look for water statics and use THOSE as the map.
612  MapShape shape;
613  shape.z = srec.z; // these will be converted below to
614  shape.height = 0; // make the map "solid"
615  shape.flags = static_cast<unsigned char>( polflags );
616  // no matter what, the lowest level is gradual
617  shape.flags |= FLAG::GRADUAL;
618  shapes.push_back( shape );
619 
620  // for wall flag - map tile always height 0, at bottom. if map tile has height, add it as
621  // a static
622  if ( srec.height != 0 )
623  {
624  MapShape _shape;
625  _shape.z = srec.z;
626  _shape.height = srec.height;
627  _shape.flags = polflags;
628  shapes.push_back( _shape );
629  }
630  continue;
631  }
632 
633  MapShape& prev = shapes.back();
634  // we're adding it.
635  MapShape shape;
636  shape.z = srec.z;
637  shape.height = srec.height;
638  shape.flags = polflags;
639 
640  // always add the map shape seperately
641  if ( shapes.size() == 1 )
642  {
643  shapes.push_back( shape );
644  continue;
645  }
646 
647  if ( shape.z < prev.z + prev.height )
648  {
649  // things can't exist in the same place.
650  // shrink the bottom part of this shape.
651  // if that would give it negative height, then skip it.
652  short height_remove = prev.z + prev.height - shape.z;
653  if ( height_remove <= shape.height )
654  {
655  shape.z += height_remove;
656  shape.height -= height_remove;
657  }
658  else
659  { // example: 5530, 14
660  continue;
661  }
662  }
663 
664  // sometimes water has "sand" a couple z-coords above it.
665  // We'll try to detect this (really, anything that is up to 4 dist from water)
666  // and extend the thing above downward.
667  if ( ( prev.flags & FLAG::MOVESEA ) && ( shape.z > prev.z + prev.height ) &&
668  ( shape.z <= prev.z + prev.height + 4 ) )
669  {
670  short height_add = shape.z - prev.z - prev.height;
671  shape.z -= height_add;
672  shape.height += height_add;
673  }
674  if ( ( prev.flags & FLAG::MOVESEA ) && ( prev.z + prev.height == -5 ) &&
675  ( shape.flags & FLAG::MOVESEA ) && ( shape.z == 25 ) )
676  {
677  // oddly, there are some water tiles at z=25 in some places...I don't get it
678  continue;
679  }
680 
681  // string prevflags_s = flagstr(prev.flags);
682  // const char* prevflags = prevflags_s.c_str();
683  // string shapeflags_s = flagstr(shape.flags);
684  // const char* shapeflags = shapeflags_s.c_str();
685 
686  if ( shape.z > prev.z + prev.height )
687  {
688  //
689  // elevated above what's below, must include separately
690  //
691 
692  shapes.push_back( shape );
693  continue;
694  }
695 
696  passert_always( shape.z == prev.z + prev.height );
697 
698  if ( shape.z == prev.z + prev.height )
699  {
700  //
701  // sitting right on top of the previous solid
702  //
703 
704  // standable atop non-standable: standable
705  // nonstandable atop standable: nonstandable
706  // etc
707  bool can_combine =
708  flags_match( prev.flags, shape.flags, FLAG::BLOCKSIGHT | FLAG::BLOCKING );
709  if ( prev.flags & FLAG::MOVELAND && ~shape.flags & FLAG::BLOCKING &&
710  ~shape.flags & FLAG::MOVELAND )
711  {
712  can_combine = false;
713  }
714 
715  if ( can_combine )
716  {
717  prev.flags = shape.flags;
718  prev.height += shape.height;
719  }
720  else // if one blocks LOS, but not the other, they can't be combined this way.
721  {
722  shapes.push_back( shape );
723  continue;
724  }
725  }
726  }
727 
728  // the first StaticShape is the map base.
729  MapShape base = shapes[0];
730  shapes.erase( shapes.begin() );
731  MAPCELL cell;
732  passert_always( base.height == 0 );
733  cell.z = static_cast<signed char>(
734  base.z ); // assume now map has height=1. a static was already added if it was >0
735  cell.flags = static_cast<u8>( base.flags );
736  if ( !shapes.empty() )
737  cell.flags |= FLAG::MORE_SOLIDS;
738 
739  mapwriter.SetMapCell( x, y, cell );
740 
741  if ( !shapes.empty() )
742  {
744  total_statics += static_cast<unsigned int>( shapes.size() );
745  if ( idx2_offset == 0 )
746  idx2_offset = mapwriter.NextSolidx2Offset();
747 
748  unsigned int addindex = mapwriter.NextSolidIndex() - idx2_elem.baseindex;
749  if ( addindex > std::numeric_limits<unsigned short>::max() )
750  throw std::runtime_error( "addoffset overflow" );
751  idx2_elem.addindex[x_add][y_add] = static_cast<unsigned short>( addindex );
752  int count = static_cast<int>( shapes.size() );
753  for ( int j = 0; j < count; ++j )
754  {
755  MapShape shape = shapes[j];
756  char _z, height, flags;
757  _z = static_cast<char>( shapes[j].z );
758  height = static_cast<char>( shape.height );
759  flags = static_cast<u8>( shape.flags );
760  if ( !height ) // make 0 height solid
761  {
762  --_z;
763  ++height;
764  }
765 
766  if ( j != count - 1 )
767  flags |= FLAG::MORE_SOLIDS;
768  SOLIDS_ELEM solid;
769  solid.z = _z;
770  solid.height = height;
771  solid.flags = flags;
772  mapwriter.AppendSolid( solid );
773  }
774  }
775  }
776  }
777  if ( idx2_offset )
778  {
779  ++nonempty;
780  mapwriter.AppendSolidx2Elem( idx2_elem );
781  }
782  else
783  {
784  ++empty;
785  }
786  mapwriter.SetSolidx2Offset( x_base, y_base, idx2_offset );
787 }
788 
789 void write_multi( FILE* multis_cfg, unsigned id, FILE* multi_mul, unsigned int offset,
790  unsigned int length )
791 {
793  unsigned int count;
795  count = length / sizeof( USTRUCT_MULTI_ELEMENT_HSA );
796  else
797  count = length / sizeof elem;
798 
799  std::string type, mytype;
800  if ( BoatTypes.count( id ) )
801  type = "Boat";
802  else if ( HouseTypes.count( id ) )
803  type = "House";
804  else if ( StairTypes.count( id ) )
805  type = "Stairs";
806  else
807  {
808  ERROR_PRINT << "Type 0x" << fmt::hexu( id )
809  << " not found in uoconvert.cfg, assuming \"House\" type.\n";
810  type = "House";
811  }
812  mytype = type;
813 
814  fprintf( multis_cfg, "%s 0x%x\n", type.c_str(), id );
815  fprintf( multis_cfg, "{\n" );
816 
817  if ( fseek( multi_mul, offset, SEEK_SET ) != 0 )
818  {
819  throw std::runtime_error( "write_multi(): fseek() failed" );
820  }
821 
822 
823  bool first = true;
824  while ( count-- )
825  {
826  if ( fread( &elem, sizeof elem, 1, multi_mul ) != 1 )
827  {
828  throw std::runtime_error( "write_multi(): fread() failed" );
829  }
830 
832  {
833  if ( fseek( multi_mul, 4, SEEK_CUR ) != 0 )
834  throw std::runtime_error( "write_multi(): fseek() failed" );
835  }
836 
837  if ( elem.graphic == GRAPHIC_NODRAW )
838  continue;
839 
840  if ( elem.flags )
841  type = "static";
842  else
843  type = "dynamic";
844 
845  // boats typically have as their first element the "mast", but flagged as dynamic.
846  if ( mytype == "Boat" )
847  {
848  if ( first && elem.graphic != 1 )
849  type = "static";
850  }
851  std::string comment;
853  {
854  USTRUCT_TILE_HSA tile;
855  readtile( elem.graphic, &tile );
856  comment.assign( tile.name, sizeof( tile.name ) );
857  }
858  else
859  {
860  USTRUCT_TILE tile;
861  readtile( elem.graphic, &tile );
862  comment.assign( tile.name, sizeof( tile.name ) );
863  }
864  fprintf( multis_cfg, " %-7s 0x%04x %4d %4d %4d // %s\n", type.c_str(), elem.graphic,
865  elem.x, elem.y, elem.z, comment.c_str() );
866  first = false;
867  }
868  fprintf( multis_cfg, "}\n" );
869  fprintf( multis_cfg, "\n" );
870 }
871 
872 void create_multis_cfg( FILE* multi_idx, FILE* multi_mul, FILE* multis_cfg )
873 {
874  if ( fseek( multi_idx, 0, SEEK_SET ) != 0 )
875  throw std::runtime_error( "create_multis_cfg: fseek failed" );
876  unsigned count = 0;
878  for ( int i = 0; fread( &idxrec, sizeof idxrec, 1, multi_idx ) == 1; ++i )
879  {
880  const USTRUCT_VERSION* vrec = NULL;
881 
882  if ( check_verdata( VERFILE_MULTI_MUL, i, vrec ) )
883  {
884  write_multi( multis_cfg, i, verfile, vrec->filepos, vrec->length );
885  ++count;
886  }
887  else
888  {
889  if ( idxrec.offset == 0xFFffFFffLu )
890  continue;
891 
892  write_multi( multis_cfg, i, multi_mul, idxrec.offset, idxrec.length );
893  ++count;
894  }
895  }
896  INFO_PRINT << count << " multi definitions written to multis.cfg\n";
897 }
898 
900 {
901  FILE* multi_idx = open_uo_file( "multi.idx" );
902  FILE* multi_mul = open_uo_file( "multi.mul" );
903 
904  FILE* multis_cfg = fopen( "multis.cfg", "wt" );
905 
906  create_multis_cfg( multi_idx, multi_mul, multis_cfg );
907 
908  fclose( multis_cfg );
909 
910  fclose( multi_idx );
911  fclose( multi_mul );
912 }
913 void write_flags( FILE* fp, unsigned int flags )
914 {
915  if ( flags & FLAG::MOVELAND )
916  fprintf( fp, " MoveLand 1\n" );
917  if ( flags & FLAG::MOVESEA )
918  fprintf( fp, " MoveSea 1\n" );
919  if ( flags & FLAG::BLOCKSIGHT )
920  fprintf( fp, " BlockSight 1\n" );
921  if ( ~flags & FLAG::OVERFLIGHT )
922  fprintf( fp, " OverFlight 0\n" );
923  if ( flags & FLAG::ALLOWDROPON )
924  fprintf( fp, " AllowDropOn 1\n" );
925  if ( flags & FLAG::GRADUAL )
926  fprintf( fp, " Gradual 1\n" );
927  if ( flags & FLAG::STACKABLE )
928  fprintf( fp, " Stackable 1\n" );
929  if ( flags & FLAG::BLOCKING )
930  fprintf( fp, " Blocking 1\n" );
931  if ( flags & FLAG::MOVABLE )
932  fprintf( fp, " Movable 1\n" );
933  if ( flags & FLAG::EQUIPPABLE )
934  fprintf( fp, " Equippable 1\n" );
935  if ( flags & FLAG::DESC_PREPEND_A )
936  fprintf( fp, " DescPrependA 1\n" );
937  if ( flags & FLAG::DESC_PREPEND_AN )
938  fprintf( fp, " DescPrependAn 1\n" );
939 }
940 
942 {
943  FILE* fp = fopen( "tiles.cfg", "wt" );
944  int mountCount;
945  char name[21];
946 
947  unsigned count = 0;
948  for ( unsigned int graphic_i = 0; graphic_i <= Plib::systemstate.config.max_tile_id; ++graphic_i )
949  {
950  u16 graphic = static_cast<u16>( graphic_i );
951  USTRUCT_TILE tile;
953  {
954  USTRUCT_TILE_HSA newtile;
955  read_objinfo( graphic, newtile );
956  tile.anim = newtile.anim;
957  tile.flags = newtile.flags;
958  tile.height = newtile.height;
959  tile.layer = newtile.layer;
960  memcpy( tile.name, newtile.name, sizeof tile.name );
961  tile.unk14 = newtile.unk14;
962  tile.unk15 = newtile.unk15;
963  tile.unk6 = newtile.unk6;
964  tile.unk7 = newtile.unk7;
965  tile.unk8 = newtile.unk8;
966  tile.unk9 = newtile.unk9;
967  tile.weight = newtile.weight;
968  }
969  else
970  read_objinfo( graphic, tile );
971  mountCount = static_cast<int>( MountTypes.count( graphic ) );
972 
973  if ( tile.name[0] == '\0' && tile.flags == 0 && tile.layer == 0 && tile.height == 0 &&
974  mountCount == 0 )
975  {
976  continue;
977  }
978  unsigned int flags =
979  polflags_from_tileflags( graphic, tile.flags, cfg_use_no_shoot, cfg_LOS_through_windows );
980  if ( mountCount != 0 )
981  {
982  tile.layer = 25;
983  flags |= FLAG::EQUIPPABLE;
984  }
985 
986  memset( name, 0, sizeof name );
987  memcpy( name, tile.name, sizeof tile.name );
988 
989  fprintf( fp, "tile 0x%x\n", graphic );
990  fprintf( fp, "{\n" );
991  fprintf( fp, " Desc %s\n", name );
992  fprintf( fp, " UoFlags 0x%08lx\n", static_cast<unsigned long>( tile.flags ) );
993  if ( tile.layer )
994  fprintf( fp, " Layer %u\n", tile.layer );
995  fprintf( fp, " Height %u\n", tile.height );
996  fprintf( fp, " Weight %u\n", tile.weight );
997  write_flags( fp, flags );
998  fprintf( fp, "}\n" );
999  fprintf( fp, "\n" );
1000  ++count;
1001  }
1002  fclose( fp );
1003 
1004  INFO_PRINT << count << " tile definitions written to tiles.cfg\n";
1005 }
1006 
1008 {
1009  FILE* fp = fopen( "landtiles.cfg", "wt" );
1010  unsigned count = 0;
1011 
1012  for ( u16 i = 0; i <= 0x3FFF; ++i )
1013  {
1014  USTRUCT_LAND_TILE landtile;
1015  if ( cfg_use_new_hsa_format )
1016  {
1017  USTRUCT_LAND_TILE_HSA newlandtile;
1018  readlandtile( i, &newlandtile );
1019  landtile.flags = newlandtile.flags;
1020  landtile.unk = newlandtile.unk;
1021  memcpy( landtile.name, newlandtile.name, sizeof landtile.name );
1022  }
1023  else
1024  readlandtile( i, &landtile );
1025 
1026  if ( landtile.name[0] || landtile.flags )
1027  {
1028  fprintf( fp, "landtile 0x%x\n", i );
1029  fprintf( fp, "{\n" );
1030  fprintf( fp, " Name %s\n", landtile.name );
1031  fprintf( fp, " UoFlags 0x%08lx\n", static_cast<unsigned long>( landtile.flags ) );
1032 
1033  unsigned int flags = polflags_from_landtileflags( i, landtile.flags );
1034  flags &= ~FLAG::MOVABLE; // movable makes no sense for landtiles
1035  write_flags( fp, flags );
1036  fprintf( fp, "}\n" );
1037  fprintf( fp, "\n" );
1038  ++count;
1039  }
1040  }
1041  fclose( fp );
1042 
1043  INFO_PRINT << count << " landtile definitions written to landtiles.cfg\n";
1044 }
1045 
1047 {
1048  const std::vector<std::string>& binArgs = programArgs();
1049 
1050  /**********************************************
1051  * show help
1052  **********************************************/
1053  if ( binArgs.size() == 1 )
1054  {
1055  showHelp();
1056  return 0; // return "okay"
1057  }
1058 
1059  /**********************************************
1060  * TODO: rework the following cruft from former uoconvert.cpp
1061  **********************************************/
1063  std::string argvalue = programArgsFindEquals( "uodata=", "" );
1064  if ( !argvalue.empty() )
1065  {
1068  Clib::normalized_dir_form( Plib::systemstate.config.uo_datafile_root );
1069  }
1070  else
1071  {
1072  INFO_PRINT << "Reading pol.cfg.\n";
1073  Clib::ConfigFile cf( "pol.cfg" );
1074  Clib::ConfigElem elem;
1075 
1076  cf.readraw( elem );
1077  Plib::systemstate.config.uo_datafile_root = elem.remove_string( "UoDataFileRoot" );
1079  Clib::normalized_dir_form( Plib::systemstate.config.uo_datafile_root );
1080 
1081  unsigned short max_tile = elem.remove_ushort( "MaxTileID", 0x0 );
1082 
1083  if ( max_tile == UOBJ_DEFAULT_MAX || max_tile == UOBJ_SA_MAX || max_tile == UOBJ_HSA_MAX )
1085  }
1086 
1087  unsigned short max_tile =
1088  static_cast<unsigned short>( programArgsFindEquals( "maxtileid=", 0x0, true ) );
1089  if ( max_tile == UOBJ_DEFAULT_MAX || max_tile == UOBJ_SA_MAX || max_tile == UOBJ_HSA_MAX )
1091 
1092 
1093  std::string main_cfg = "uoconvert.cfg";
1094  if ( Clib::FileExists( main_cfg.c_str() ) )
1095  {
1096  std::string temp;
1097  Clib::ConfigElem elem;
1098  INFO_PRINT << "Reading uoconvert.cfg.\n";
1099  Clib::ConfigFile cf_main( main_cfg.c_str() );
1100  while ( cf_main.read( elem ) )
1101  {
1102  if ( elem.type_is( "MultiTypes" ) )
1103  {
1104  temp = elem.remove_string( "Boats" );
1105  ISTRINGSTREAM is_boats( temp );
1106  std::string graphicnum;
1107  while ( is_boats >> graphicnum )
1108  UoConvert::BoatTypes.insert( strtoul( graphicnum.c_str(), NULL, 0 ) );
1109 
1110  temp = elem.remove_string( "Houses" );
1111  ISTRINGSTREAM is_houses( temp );
1112  while ( is_houses >> graphicnum )
1113  UoConvert::HouseTypes.insert( strtoul( graphicnum.c_str(), NULL, 0 ) );
1114 
1115  temp = elem.remove_string( "Stairs" );
1116  ISTRINGSTREAM is_stairs( temp );
1117  while ( is_stairs >> graphicnum )
1118  UoConvert::StairTypes.insert( strtoul( graphicnum.c_str(), NULL, 0 ) );
1119  }
1120  else if ( elem.type_is( "LOSOptions" ) )
1121  {
1122  if ( elem.has_prop( "UseNoShoot" ) )
1123  UoConvert::cfg_use_no_shoot = elem.remove_bool( "UseNoShoot" );
1124 
1125  if ( elem.has_prop( "LOSThroughWindows" ) )
1126  UoConvert::cfg_LOS_through_windows = elem.remove_bool( "LOSThroughWindows" );
1127  }
1128  else if ( elem.type_is( "Mounts" ) )
1129  {
1130  std::string graphicnum;
1131  temp = elem.remove_string( "Tiles" );
1132  ISTRINGSTREAM is_mounts( temp );
1133  while ( is_mounts >> graphicnum )
1134  {
1135  UoConvert::MountTypes.insert( strtoul( graphicnum.c_str(), NULL, 0 ) );
1136  }
1137  }
1138  else if ( elem.type_is( "StaticOptions" ) )
1139  {
1140  if ( elem.has_prop( "MaxStaticsPerBlock" ) )
1141  {
1142  UoConvert::cfg_max_statics_per_block = elem.remove_int( "MaxStaticsPerBlock" );
1143 
1145  {
1147  INFO_PRINT << "max. Statics per Block limited to "
1148  << UoConvert::cfg_max_statics_per_block << " Items\n";
1149  }
1150  else if ( UoConvert::cfg_max_statics_per_block < 0 )
1152  }
1153 
1154  if ( elem.has_prop( "WarningStaticsPerBlock" ) )
1155  {
1156  UoConvert::cfg_warning_statics_per_block = elem.remove_int( "WarningStaticsPerBlock" );
1157 
1159  {
1161  INFO_PRINT << "max. Statics per Block for Warning limited to "
1163  }
1166  }
1167 
1168  if ( elem.has_prop( "ShowIllegalGraphicWarning" ) )
1170  elem.remove_bool( "ShowIllegalGraphicWarning" );
1171  }
1172  else if ( elem.type_is( "TileOptions" ) )
1173  {
1174  if ( elem.has_prop( "ShowRoofAndPlatformWarning" ) )
1176  elem.remove_bool( "ShowRoofAndPlatformWarning" );
1177  }
1178  else if ( elem.type_is( "ClientOptions" ) )
1179  {
1180  if ( elem.has_prop( "UseNewHSAFormat" ) )
1181  UoConvert::cfg_use_new_hsa_format = elem.remove_bool( "UseNewHSAFormat" );
1182  }
1183  }
1184  }
1185 
1186  std::string command = binArgs[1];
1187  if ( command == "uoptomul" )
1188  {
1189  // this is kludgy and doesn't take into account the UODataPath. Mostly a proof of concept now.
1190  UoConvert::uo_mapid = programArgsFindEquals( "mapid=", 0, false );
1191 
1192  std::string mul_mapfile = "map" + to_string( uo_mapid ) + ".mul";
1193  std::string uop_mapfile = "map" + to_string( uo_mapid ) + "LegacyMUL.uop";
1194 
1195  auto maphash = []( int mapid, size_t chunkidx ) {
1196  fmt::Writer tmp;
1197  tmp << "build/map" << mapid << "legacymul/" << fmt::pad(chunkidx,8,'0') << ".dat";
1198  return HashLittle2( tmp.str() );
1199  };
1200 
1201  std::ifstream ifs( uop_mapfile, std::ifstream::binary );
1202  if ( !ifs )
1203  {
1204  ERROR_PRINT << "Error when opening mapfile: " << uop_mapfile << '\n';
1205  return 1;
1206  }
1207 
1208  kaitai::kstream ks( &ifs );
1209  uop_t uopfile( &ks );
1210 
1211  // TODO: read all blocks
1212  std::map<uint64_t, uop_t::file_t*> filemap;
1213  uop_t::block_addr_t* currentblock = uopfile.header()->firstblock();
1214  for ( auto file : *currentblock->block_body()->files() )
1215  {
1216  if ( file == nullptr )
1217  continue;
1218  if ( file->decompressed_size() == 0 )
1219  continue;
1220  filemap[file->filehash()] = file;
1221  }
1222 
1223  if ( uopfile.header()->nfiles() != filemap.size() )
1224  INFO_PRINT << "Warning: not all chunks read (" << filemap.size() << "/"
1225  << uopfile.header()->nfiles() << ")\n";
1226 
1227  std::ofstream ofs( mul_mapfile, std::ofstream::binary );
1228  for ( size_t i = 0; i < filemap.size(); i++ )
1229  {
1230  auto fileitr = filemap.find( maphash( uo_mapid, i ) );
1231  if ( fileitr == filemap.end() )
1232  {
1233  INFO_PRINT << "Couldn't find file hash: " << maphash( uo_mapid, i );
1234  continue;
1235  }
1236 
1237  auto file = fileitr->second;
1238  ofs << file->data()->filebytes();
1239  INFO_PRINT << "Wrote: " << i + 1 << "/" << filemap.size() << '\n';
1240  }
1241  INFO_PRINT << "Done converting.\n";
1242  }
1243  else if ( command == "map" )
1244  {
1245  UoConvert::uo_mapid = programArgsFindEquals( "mapid=", 0, false );
1246  UoConvert::uo_usedif = programArgsFindEquals( "usedif=", 0, false );
1247  UoConvert::uo_readuop = (bool)programArgsFindEquals( "readuop=", 1, false );
1248 
1249  std::string realm = programArgsFindEquals( "realm=", "britannia" );
1250  int default_width = 6144;
1251  int default_height = 4096;
1252  switch ( UoConvert::uo_mapid )
1253  {
1254  case 0:
1255  case 1:
1256  break;
1257  case 2: // ilshenar:
1258  default_width = 2304;
1259  default_height = 1600;
1260  break;
1261  case 3: // malas
1262  default_width = 2560;
1263  default_height = 2048;
1264  break;
1265  case 4: // tokuno
1266  default_width = 1448;
1267  default_height = 1448;
1268  break;
1269  case 5: // termur
1270  default_width = 1280;
1271  default_height = 4096;
1272  break;
1273  }
1274  int width = programArgsFindEquals( "width=", default_width, false );
1275  int height = programArgsFindEquals( "height=", default_height, false );
1276  UoConvert::uo_map_width = static_cast<unsigned short>( width );
1277  UoConvert::uo_map_height = static_cast<unsigned short>( height );
1278 
1281 
1282  int x = programArgsFindEquals( "x=", -1, false );
1283  int y = programArgsFindEquals( "y=", -1, false );
1284 
1285  // britannia: realm=main mapid=0 width=6144 height=4096
1286  // ilshenar: realm=ilshenar mapid=2 width=2304 height=1600
1287  // malas: realm=malas mapid=3 width=2560 height=2048
1288  // tokuno: realm=tokuno mapid=4 width=1448 height=1448
1289  // termur: realm=termur mapid=5 width=1280 height=4096
1290 
1291  if ( x >= 0 && y >= 0 )
1292  {
1293  UoConvert::update_map( realm, static_cast<u16>( x ), static_cast<u16>( y ) );
1294  }
1295  else
1296  {
1297  UoConvert::create_map( realm, static_cast<unsigned short>( width ),
1298  static_cast<unsigned short>( height ) );
1299  }
1300  }
1301  else if ( command == "statics" )
1302  {
1303  std::string realm = programArgsFindEquals( "realm=", "britannia" );
1304  Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realm );
1305 
1306  UoConvert::uo_mapid = descriptor.uomapid;
1307  UoConvert::uo_usedif = descriptor.uodif;
1308  UoConvert::uo_map_width = static_cast<unsigned short>( descriptor.width );
1309  UoConvert::uo_map_height = static_cast<unsigned short>( descriptor.height );
1310 
1313 
1315  }
1316  else if ( command == "multis" )
1317  {
1321  }
1322  else if ( command == "tiles" )
1323  {
1327  }
1328  else if ( command == "landtiles" )
1329  {
1333  }
1334  else if ( command == "maptile" )
1335  {
1336  std::string realm = programArgsFindEquals( "realm=", "britannia" );
1337  Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realm );
1338 
1339  UoConvert::uo_mapid = descriptor.uomapid;
1340  UoConvert::uo_usedif = descriptor.uodif;
1341  UoConvert::uo_map_width = static_cast<unsigned short>( descriptor.width );
1342  UoConvert::uo_map_height = static_cast<unsigned short>( descriptor.height );
1343 
1346 
1347  UoConvert::create_maptile( realm );
1348  }
1349  else if ( command == "flags" )
1350  {
1352  }
1353  else // unknown option
1354  {
1355  showHelp();
1356  return 1;
1357  }
1359  return 0;
1360 }
1361 } // namespace UoConvert
1362 } // namespace Pol
1363 
1367 
1368 int main( int argc, char* argv[] )
1369 {
1371  UoConvertMain->start( argc, argv );
1372 }
unsigned short landtile
Definition: maptile.h:21
void create_maptile(const std::string &realmname)
unsigned char u8
Definition: rawtypes.h:25
void AppendSolid(const SOLIDS_ELEM &solid)
Definition: mapwriter.cpp:299
static RealmDescriptor Load(const std::string &realm_name, const std::string &realm_path="")
void readtile(unsigned short tilenum, USTRUCT_TILE *tile)
Definition: uofile01.cpp:89
std::string remove_string(const char *propname)
Definition: cfgfile.cpp:381
Definition: uop.h:15
const std::vector< std::string > & programArgs() const
bool operator()(const StaticRec &a, const StaticRec &b)
unsigned int flags
Definition: mapshape.h:20
std::vector< StaticRec > StaticList
Definition: udatfile.h:38
void readstatics(StaticList &vec, unsigned short x, unsigned short y)
Definition: uofile07.cpp:20
SystemState systemstate
Definition: systemstate.cpp:12
Core::PolConfig config
Definition: systemstate.h:43
bool is_no_draw(USTRUCT_MAPINFO &mi)
void open_uo_data_files(void)
Definition: uofile00.cpp:91
void clear_tiledata()
Definition: uofile01.cpp:389
unsigned with_more_solids
char * binary(unsigned int val, int nbits)
#define SOLIDX_X_SIZE
Definition: mapblob.h:10
bool cfg_show_illegal_graphic_warning
Definition: polfile1.cpp:28
std::set< unsigned int > HouseTypes
bool flags_match(unsigned int f1, unsigned int f2, unsigned char bits_compare)
void create_multis_cfg()
void read_objinfo(u16 graphic, struct USTRUCT_TILE &objinfo)
Definition: uofile01.cpp:223
STL namespace.
std::set< unsigned int > MountTypes
signed char z
Definition: mapblob.h:33
int remove_int(const char *propname)
Definition: cfgfile.cpp:340
bool is_cave_exit(USTRUCT_MAPINFO &mi)
void start(int argc, char *argv[])
Definition: ProgramMain.cpp:42
std::set< unsigned int > BoatTypes
bool uo_readuop
Definition: uofile00.cpp:87
bool cfg_show_roof_and_platform_warning
Definition: mapfunc.cpp:20
#define UOBJ_SA_MAX
Definition: objtype.h:16
bool differby_exactly(unsigned char f1, unsigned char f2, unsigned char bits)
unsigned short addindex[SOLIDX_X_SIZE][SOLIDX_Y_SIZE]
Definition: mapblob.h:29
unsigned int max_tile_id
Definition: polcfg.h:61
bool cfg_use_new_hsa_format
Definition: uofile02.cpp:40
void readlandtile(unsigned short tilenum, USTRUCT_LAND_TILE *landtile)
Definition: uofile01.cpp:163
void readraw(ConfigElem &elem)
Definition: cfgfile.cpp:1028
#define UOBJ_HSA_MAX
Definition: objtype.h:15
bool check_verdata(unsigned int file, unsigned int block, const Core::USTRUCT_VERSION *&vrec)
Definition: uofile01.cpp:70
signed char z
Definition: mapcell.h:50
#define UOBJ_DEFAULT_MAX
Definition: objtype.h:17
int uo_mapid
Definition: uofile00.cpp:85
#define VERFILE_MULTI_MUL
Definition: uofilei.h:55
void rawstaticfullread()
Definition: uofile02.cpp:85
void write_flags(FILE *fp, unsigned int flags)
unsigned short u16
Definition: rawtypes.h:26
std::vector< file_t * > * files() const
Definition: uop.h:96
unsigned int landtile_uoflags(unsigned short landtile)
Definition: landtile.cpp:41
void safe_getmapinfo(unsigned short x, unsigned short y, short *z, USTRUCT_MAPINFO *mi)
Definition: uofile08.cpp:129
USTRUCT_IDX idxrec
Definition: uofile02.cpp:34
short get_lowestadjacentz(unsigned short x, unsigned short y, short z)
unsigned int NextSolidIndex()
Definition: mapwriter.cpp:289
int cfg_max_statics_per_block
Definition: uofile02.cpp:38
u32 polflags_from_tileflags(unsigned short tile, u32 uoflags, bool use_no_shoot, bool LOS_through_windows)
Definition: mapfunc.cpp:71
void write_multi(FILE *multis_cfg, unsigned id, FILE *multi_mul, unsigned int offset, unsigned int length)
void AppendSolidx2Elem(const SOLIDX2_ELEM &elem)
Definition: mapwriter.cpp:305
void create_landtiles_cfg()
u32 polflags_from_landtileflags(unsigned short tile, u32 lt_flags)
Definition: mapfunc.cpp:214
#define MAX_STATICS_PER_BLOCK
Definition: uofile.h:22
unsigned char flags
Definition: mapcell.h:51
FILE * verfile
Definition: uofile00.cpp:24
unsigned short uo_map_height
Definition: uofile00.cpp:90
unsigned int flags
Definition: udatfile.h:20
#define SOLIDX_Y_SIZE
Definition: mapblob.h:14
void rawmapfullread()
Definition: uofile08.cpp:50
uint64_t HashLittle2(std::string s)
Definition: uophash.h:9
unsigned total_statics
void SetMapCell(unsigned short x, unsigned short y, MAPCELL cell)
Definition: mapwriter.cpp:217
std::set< unsigned int > StairTypes
void read_uo_data(void)
Definition: uofile01.cpp:414
signed char z
Definition: udatfile.h:22
unsigned char flags
Definition: mapblob.h:35
bool is_cave_shadow(USTRUCT_MAPINFO &mi)
const unsigned MAPTILE_CHUNK
Definition: maptile.h:13
block_body_t * block_body()
Definition: uop.cpp:40
#define ISTRINGSTREAM
Definition: stlutil.h:73
bool type_is(const char *name) const
Definition: cfgfile.cpp:95
bool has_prop(const char *propname) const
Definition: cfgfile.cpp:112
unsigned short remove_ushort(const char *propname)
Definition: cfgfile.cpp:318
long long ellapsed() const
Definition: timer.cpp:46
std::string name
Definition: osmod.cpp:943
unsigned char height
Definition: mapblob.h:34
block_addr_t * firstblock() const
Definition: uop.h:152
FILE * open_uo_file(const std::string &filename_part)
Definition: uofile00.cpp:47
unsigned short uo_map_width
Definition: uofile00.cpp:89
void update_map(const std::string &realm, unsigned short x, unsigned short y)
void SetSolidx2Offset(unsigned short x_base, unsigned short y_base, unsigned int offset)
Definition: mapwriter.cpp:311
std::string programArgsFindEquals(const std::string &filter, std::string defaultVal) const
int uo_usedif
Definition: uofile00.cpp:86
#define ERROR_PRINT
Definition: logfacility.h:230
void ProcessSolidBlock(unsigned short x_base, unsigned short y_base, MapWriter &mapwriter)
unsigned char polmap_flags_from_landtile(unsigned short landtile)
std::string normalized_dir_form(const std::string &istr)
Definition: fileutil.cpp:25
std::string uo_datafile_root
Definition: polcfg.h:27
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
bool cfg_LOS_through_windows
unsigned int baseindex
Definition: mapblob.h:28
void CreateNewFiles(const std::string &realm_name, unsigned short width, unsigned short height)
Definition: mapwriter.cpp:126
#define passert_always(exp)
Definition: passert.h:80
#define INFO_PRINT
Definition: logfacility.h:223
unsigned short graphic
Definition: udatfile.h:21
uint32_t nfiles() const
Definition: uop.h:154
unsigned int NextSolidx2Offset()
Definition: mapwriter.cpp:294
bool otherflags_match(unsigned char f1, unsigned char f2, unsigned char bits_exclude)
void create_map(const std::string &realm, unsigned short width, unsigned short height)
Definition: berror.cpp:12
int write_pol_static_files(const std::string &realm)
Definition: polfile1.cpp:50
bool remove_bool(const char *propname)
Definition: cfgfile.cpp:426
void OpenExistingFiles(const std::string &realm_name)
Definition: mapwriter.cpp:147
#define GRAPHIC_NODRAW
Definition: objtype.h:19
header_t * header() const
Definition: uop.h:217
int cfg_warning_statics_per_block
Definition: uofile02.cpp:39