Pol  Revision:e09f183
uoconvert/uoconvert.cpp
Go to the documentation of this file.
00001 /*
00002 History
00003 =======
00004 2005/01/13 Shinigami: added support for Samurai Empire Map Tokuno
00005 processsolidblock - can handle maps without 16 tile bounds
00006 create_tiles_cfg - will handle tile names with 20 chars too
00007 2005/07/05 Shinigami: added uoconvert.cfg option *StaticsPerBlock (hard limit is set to 10000)
00008 2005/07/16 Shinigami: added uoconvert.cfg flag ShowIllegalGraphicWarning
00009 2006/04/09 Shinigami: added uoconvert.cfg flag ShowRoofAndPlatformWarning
00010 2006/05/26 Shinigami: there was another part with ShowRoofAndPlatformWarning-check, commented out
00011 2009/12/02 Turley:    added config.max_tile_id & termur support - Tomi
00012 
00013 Notes
00014 =======
00015 
00016 */
00017 
00018 
00019 #include "../pol/uofile.h"
00020 #include "../pol/objtype.h"
00021 #include "../pol/polcfg.h"
00022 #include "../pol/udatfile.h"
00023 #include "../pol/polfile.h"
00024 #include "../pol/uofilei.h"
00025 
00026 #include "../plib/mapcell.h"
00027 #include "../plib/mapblock.h"
00028 #include "../plib/mapsolid.h"
00029 #include "../plib/mapfunc.h"
00030 #include "../plib/mapserver.h"
00031 #include "../plib/mapshape.h"
00032 #include "../plib/mapwriter.h"
00033 #include "../plib/realmdescriptor.h"
00034 #include "../plib/systemstate.h"
00035 
00036 #include "../clib/stlutil.h"
00037 #include "../clib/cfgelem.h"
00038 #include "../clib/cfgfile.h"
00039 #include "../clib/cmdargs.h"
00040 #include "../clib/fileutil.h"
00041 #include "../clib/logfacility.h"
00042 #include "../clib/passert.h"
00043 #include "../clib/timer.h"
00044 
00045 #include <string>
00046 #include <set>
00047 #include <vector>
00048 #include <stdexcept>
00049 #include <limits>
00050 
00051 #ifdef _MSC_VER
00052 #pragma warning(disable:4996) // deprecation warning for fopen
00053 #endif
00054 
00055 namespace Pol {
00056   namespace Plib {
00057     std::string flagstr( unsigned char flags );
00058   }
00059   namespace Core{
00060     void safe_getmapinfo( unsigned short x, unsigned short y, short* z, USTRUCT_MAPINFO* mi );
00061   }
00062   namespace UOConvert {
00063     using namespace Core;
00064     using namespace Plib;
00065 
00066     bool cfg_use_no_shoot = 0;
00067     bool cfg_LOS_through_windows = 0;
00068 
00069     std::set<unsigned int> HouseTypes;
00070     std::set<unsigned int> BoatTypes;
00071     std::set<unsigned int> StairTypes;
00072     std::set<unsigned int> MountTypes;
00073 
00074     
00075     
00076     void generate_map();
00077     void create_map(const std::string& realm, unsigned short width, unsigned short height);
00078     void update_map(const std::string& realm, unsigned short x, unsigned short y);
00079     
00080     void create_multis_cfg();
00081     void create_tiles_cfg();
00082     void create_landtiles_cfg();
00083     void create_maptile(const std::string& realmname);
00084 
00085     void display_flags()
00086     {
00087       for ( unsigned blocking = 0; blocking <= 1; ++blocking )
00088       {
00089         for ( unsigned platform = 0; platform <= 1; ++platform )
00090         {
00091           for ( unsigned walk = 0; walk <= 1; ++walk )
00092           {
00093             for ( unsigned wall = 0; wall <= 1; ++wall )
00094             {
00095               for ( unsigned half = 0; half <= 1; ++half )
00096               {
00097                 for ( unsigned floor = 0; floor <= 1; ++floor )
00098                 {
00099                   unsigned flags = 0;
00100                   if ( blocking ) flags |= Core::USTRUCT_TILE::FLAG_BLOCKING;
00101                   if ( platform ) flags |= Core::USTRUCT_TILE::FLAG_PLATFORM;
00102                   if ( walk ) flags |= Core::USTRUCT_TILE::FLAG__WALK;
00103                   if ( wall ) flags |= Core::USTRUCT_TILE::FLAG_WALL;
00104                   if ( half ) flags |= Core::USTRUCT_TILE::FLAG_HALF_HEIGHT;
00105                   if ( floor ) flags |= Core::USTRUCT_TILE::FLAG_FLOOR;
00106 
00107                   unsigned int polflags = Plib::polflags_from_tileflags( 0x4000, flags, cfg_use_no_shoot, cfg_LOS_through_windows );
00108                   unsigned moveland = ( polflags & Plib::FLAG::MOVELAND ) ? 1 : 0;
00109                   INFO_PRINT.Format( "{} {} {} {} {} {}: {}\n" ) << blocking << platform << walk << wall << half << floor << moveland;
00110                 }
00111               }
00112             }
00113           }
00114         }
00115       }
00116     }
00117 
00118     
00119 
00120 
00121     unsigned char polmap_flags_from_landtile( unsigned short landtile )
00122     {
00123 
00124       unsigned int uoflags = landtile_uoflags( landtile );
00125 
00126       unsigned int polflags = Plib::polflags_from_tileflags( landtile, uoflags, cfg_use_no_shoot, cfg_LOS_through_windows );
00127       return static_cast<unsigned char>( polflags );
00128     }
00129 
00130 
00131     void create_maptile(const std::string& realmname)
00132     {
00133       Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realmname );
00134       uo_map_height = static_cast<unsigned short>( descriptor.height );
00135       uo_map_width = static_cast<unsigned short>( descriptor.width );
00136 
00137       INFO_PRINT << "Creating maptile file.\n"
00138         << "  Realm: " << realmname << "\n"
00139         << "  Map ID: " << descriptor.uomapid << "\n"
00140         << "  Use Dif files: " << ( descriptor.uodif ? "Yes" : "No" ) << "\n"
00141         << "  Size: " << uo_map_width << "x" << uo_map_height << "\n";
00142 
00143       auto writer = new Plib::MapWriter();
00144       writer->OpenExistingFiles( realmname );
00145 
00146       for ( unsigned short y_base = 0; y_base < uo_map_height; y_base += Plib::MAPTILE_CHUNK )
00147       {
00148         for ( unsigned short x_base = 0; x_base < uo_map_width; x_base += Plib::MAPTILE_CHUNK )
00149         {
00150           for ( unsigned short x_add = 0; x_add < Plib::MAPTILE_CHUNK; ++x_add )
00151           {
00152             for ( unsigned short y_add = 0; y_add < Plib::MAPTILE_CHUNK; ++y_add )
00153             {
00154               unsigned short x = x_base + x_add;
00155               unsigned short y = y_base + y_add;
00156 
00157               short z;
00158               Core::USTRUCT_MAPINFO mi;
00159 
00160               safe_getmapinfo( x, y, &z, &mi );
00161 
00162               if ( mi.landtile > 0x3FFF )
00163                 INFO_PRINT.Format("Tile 0x{:X} at ({},{},{}) is an invalid ID!\n") << mi.landtile << x << y << z;
00164 
00165               // for water, don't average with surrounding tiles.
00166               if ( landtile_uoflags( mi.landtile ) & Core::USTRUCT_TILE::FLAG_LIQUID )
00167                 z = mi.z;
00168 
00169               Plib::MAPTILE_CELL cell;
00170               cell.landtile = mi.landtile;
00171               cell.z = static_cast<signed char>( z );
00172               writer->SetMapTile( x, y, cell );
00173 
00174             }
00175           }
00176         }
00177         INFO_PRINT << "\rConverting: " << y_base * 100 / uo_map_height << "%";
00178       }
00179       writer->Flush();
00180       delete writer;
00181       INFO_PRINT << "\rConversion complete.\n";
00182     }
00183 
00184     class StaticsByZ
00185     {
00186     public:
00187       bool operator()( const StaticRec& a, const StaticRec& b )
00188       {
00189         return ( a.z < b.z ) ||
00190           ( ( a.z == b.z && a.height < b.height ) );
00191       }
00192     };
00193 
00194     bool flags_match( unsigned int f1, unsigned int f2, unsigned char bits_compare )
00195     {
00196       return ( f1 & bits_compare )
00197         ==
00198         ( f2 & bits_compare );
00199     }
00200 
00201     bool otherflags_match( unsigned char f1, unsigned char f2, unsigned char bits_exclude )
00202     {
00203       return ( f1 & ~bits_exclude )
00204         ==
00205         ( f2 & ~bits_exclude );
00206     }
00207 
00208     bool differby_exactly( unsigned char f1, unsigned char f2, unsigned char bits )
00209     {
00210       return ( ( f1 ^ f2 ) == bits );
00211     }
00212 
00213     void ProcessSolidBlock( unsigned short x_base, unsigned short y_base, MapWriter& mapwriter );
00214 
00215     unsigned empty = 0, nonempty = 0;
00216     unsigned total_statics = 0;
00217     unsigned with_more_solids = 0;
00218 
00219     void update_map(const std::string& realm, unsigned short x, unsigned short y)
00220     {
00221       auto mapwriter = new MapWriter();
00222       mapwriter->OpenExistingFiles( realm );
00223       rawmapfullread();
00224       rawstaticfullread();
00225       unsigned short x_base = x / SOLIDX_X_SIZE * SOLIDX_X_SIZE;
00226       unsigned short y_base = y / SOLIDX_Y_SIZE * SOLIDX_Y_SIZE;
00227 
00228       ProcessSolidBlock( x_base, y_base, *mapwriter );
00229       delete mapwriter;
00230       INFO_PRINT << "empty=" << empty << ", nonempty=" << nonempty << "\n"
00231         << "with more_solids: " << with_more_solids << "\n"
00232         << "total statics=" << total_statics << "\n";
00233     }
00234 
00235     void create_map(const std::string& realm, unsigned short width, unsigned short height)
00236     {
00237       auto mapwriter = new MapWriter();
00238       INFO_PRINT << "Creating map base and solids files.\n"
00239         << "  Realm: " << realm << "\n"
00240         << "  Map ID: " << uo_mapid << "\n"
00241         << "  Use Dif files: " << ( uo_usedif ? "Yes" : "No" ) << "\n"
00242         << "  Size: " << uo_map_width << "x" << uo_map_height << "\n"
00243         << "Initializing files: ";
00244       mapwriter->CreateNewFiles( realm, width, height );
00245       INFO_PRINT << "Done.\n";
00246       Tools::Timer<> timer;
00247       rawmapfullread();
00248       rawstaticfullread();
00249       INFO_PRINT << "  Reading mapfiles time: " << timer.ellapsed() << " ms.\n";
00250       for ( unsigned short y_base = 0; y_base < height; y_base += SOLIDX_Y_SIZE )
00251       {
00252         for ( unsigned short x_base = 0; x_base < width; x_base += SOLIDX_X_SIZE )
00253         {
00254           ProcessSolidBlock( x_base, y_base, *mapwriter );
00255         }
00256         INFO_PRINT << "\rConverting: " << y_base * 100 / height << "%";
00257       }
00258       timer.stop();
00259 
00260       mapwriter->WriteConfigFile();
00261       delete mapwriter;
00262 
00263       INFO_PRINT << "\rConversion complete.              \n"
00264         << "Conversion details:\n"
00265         << "  Total blocks: " << empty + nonempty << "\n"
00266         << "  Blocks with solids: " << nonempty << " (" << ( nonempty * 100 / ( empty + nonempty ) ) << "%)" << "\n"
00267         << "  Blocks without solids: " << empty << " (" << ( empty * 100 / ( empty + nonempty ) ) << "%)" << "\n"
00268         << "  Locations with solids: " << with_more_solids << "\n"
00269         << "  Total number of solids: " << total_statics << "\n"
00270         << "  Elapsed time: " << timer.ellapsed() << " ms.\n";
00271     }
00272 
00273     bool is_no_draw( USTRUCT_MAPINFO& mi )
00274     {
00275       return ( mi.landtile == 0x2 );
00276     }
00277 
00278     bool is_cave_exit( USTRUCT_MAPINFO& mi )
00279     {
00280       return ( mi.landtile == 0x7ec ||
00281                mi.landtile == 0x7ed ||
00282                mi.landtile == 0x7ee ||
00283                mi.landtile == 0x7ef ||
00284                mi.landtile == 0x7f0 ||
00285                mi.landtile == 0x7f1 ||
00286                mi.landtile == 0x834 ||
00287                mi.landtile == 0x835 ||
00288                mi.landtile == 0x836 ||
00289                mi.landtile == 0x837 ||
00290                mi.landtile == 0x838 ||
00291                mi.landtile == 0x839 ||
00292                mi.landtile == 0x1d3 ||
00293                mi.landtile == 0x1d4 ||
00294                mi.landtile == 0x1d5 ||
00295                mi.landtile == 0x1d6 ||
00296                mi.landtile == 0x1d7 ||
00297                mi.landtile == 0x1d8 ||
00298                mi.landtile == 0x1d9 ||
00299                mi.landtile == 0x1da
00300                );
00301     }
00302 
00303     bool is_cave_shadow( USTRUCT_MAPINFO& mi )
00304     {
00305       return ( mi.landtile == 0x1db || // shadows above caves
00306                mi.landtile == 0x1ae || // more shadows above caves
00307                mi.landtile == 0x1af ||
00308                mi.landtile == 0x1b0 ||
00309                mi.landtile == 0x1b1 ||
00310                mi.landtile == 0x1b2 ||
00311                mi.landtile == 0x1b3 ||
00312                mi.landtile == 0x1b4 ||
00313                mi.landtile == 0x1b5
00314                );
00315     }
00316 
00317     short get_lowestadjacentz( unsigned short x, unsigned short y, short z )
00318     {
00319       USTRUCT_MAPINFO mi;
00320       short z0;
00321       short lowest_z = z;
00322       bool cave_override = false;
00323 
00324       if ( ( x - 1 >= 0 ) && ( y - 1 >= 0 ) )
00325       {
00326         safe_getmapinfo( x - 1, y - 1, &z0, &mi );
00327 
00328         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00329           z0 = z;
00330 
00331         if ( is_no_draw( mi ) )
00332           cave_override = true;
00333 
00334         if ( z0 < lowest_z )
00335         {
00336           lowest_z = z0;
00337         }
00338       }
00339 
00340       if ( x - 1 >= 0 )
00341       {
00342         safe_getmapinfo( x - 1, y, &z0, &mi );
00343 
00344         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00345           z0 = z;
00346 
00347         if ( is_no_draw( mi ) )
00348           cave_override = true;
00349 
00350         if ( z0 < lowest_z )
00351         {
00352           lowest_z = z0;
00353         }
00354       }
00355 
00356       if ( ( x - 1 >= 0 ) && ( y + 1 < uo_map_height ) )
00357       {
00358         safe_getmapinfo( x - 1, y + 1, &z0, &mi );
00359 
00360         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00361           z0 = z;
00362 
00363         if ( is_no_draw( mi ) )
00364           cave_override = true;
00365 
00366         if ( z0 < lowest_z )
00367         {
00368           lowest_z = z0;
00369         }
00370       }
00371 
00372       if ( y - 1 >= 0 )
00373       {
00374         safe_getmapinfo( x, y - 1, &z0, &mi );
00375 
00376         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00377           z0 = z;
00378 
00379         if ( is_no_draw( mi ) )
00380           cave_override = true;
00381 
00382         if ( z0 < lowest_z )
00383         {
00384           lowest_z = z0;
00385         }
00386       }
00387 
00388       if ( ( y - 1 >= 0 ) && ( x + 1 < uo_map_width ) )
00389       {
00390         safe_getmapinfo( x + 1, y - 1, &z0, &mi );
00391 
00392         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00393           z0 = z;
00394 
00395         if ( is_no_draw( mi ) )
00396           cave_override = true;
00397 
00398         if ( z0 < lowest_z )
00399         {
00400           lowest_z = z0;
00401         }
00402       }
00403 
00404       if ( x + 1 < uo_map_width )
00405       {
00406         safe_getmapinfo( x + 1, y, &z0, &mi );
00407 
00408         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00409           z0 = z;
00410 
00411         if ( is_no_draw( mi ) )
00412           cave_override = true;
00413 
00414         if ( z0 < lowest_z )
00415         {
00416           lowest_z = z0;
00417         }
00418       }
00419 
00420       if ( ( x + 1 < uo_map_width ) && ( y + 1 < uo_map_height ) )
00421       {
00422         safe_getmapinfo( x + 1, y + 1, &z0, &mi );
00423 
00424         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00425           z0 = z;
00426 
00427         if ( is_no_draw( mi ) )
00428           cave_override = true;
00429 
00430         if ( z0 < lowest_z )
00431         {
00432           lowest_z = z0;
00433         }
00434       }
00435 
00436       if ( y + 1 < uo_map_height )
00437       {
00438         safe_getmapinfo( x, y + 1, &z0, &mi );
00439 
00440         if ( is_cave_shadow( mi ) || is_cave_exit( mi ) )
00441           z0 = z;
00442 
00443         if ( is_no_draw( mi ) )
00444           cave_override = true;
00445 
00446         if ( z0 < lowest_z )
00447         {
00448           lowest_z = z0;
00449         }
00450       }
00451 
00452       if ( cave_override )
00453         return z;
00454       else
00455         return lowest_z;
00456     }
00457 
00458     void ProcessSolidBlock( unsigned short x_base, unsigned short y_base, MapWriter& mapwriter )
00459     {
00460       unsigned int idx2_offset = 0;
00461       SOLIDX2_ELEM idx2_elem;
00462       memset( &idx2_elem, 0, sizeof idx2_elem );
00463       idx2_elem.baseindex = mapwriter.NextSolidIndex();
00464 
00465       unsigned short x_add_max = SOLIDX_X_SIZE, y_add_max = SOLIDX_Y_SIZE;
00466       if ( x_base + x_add_max > uo_map_width )
00467         x_add_max = uo_map_width - x_base;
00468       if ( y_base + y_add_max > uo_map_height )
00469         y_add_max = uo_map_height - y_base;
00470 
00471       for ( unsigned short x_add = 0; x_add < x_add_max; ++x_add )
00472       {
00473         for ( unsigned short y_add = 0; y_add < y_add_max; ++y_add )
00474         {
00475           unsigned short x = x_base + x_add;
00476           unsigned short y = y_base + y_add;
00477 
00478           StaticList statics;
00479 
00480           // read the map, and treat it like a static.
00481           short z;
00482           USTRUCT_MAPINFO mi;
00483 
00484           safe_getmapinfo( x, y, &z, &mi );
00485 
00486           if ( mi.landtile > 0x3FFF )
00487             INFO_PRINT.Format( "Tile 0x{:X} at ({},{},{}) is an invalid ID!\n" ) << mi.landtile << x << y << z;
00488 
00489           // for water, don't average with surrounding tiles.
00490           if ( landtile_uoflags( mi.landtile ) & USTRUCT_TILE::FLAG_LIQUID )
00491             z = mi.z;
00492           short low_z = get_lowestadjacentz( x, y, z );
00493 
00494           short lt_height = z - low_z;
00495           z = low_z;
00496 
00497           if ( mi.landtile > 0x3FFF )
00498             INFO_PRINT.Format( "Tile 0x{:X} at ({},{},{}) is an invalid ID!\n" ) << mi.landtile << x << y << z;
00499 
00500           unsigned int lt_flags = landtile_uoflags( mi.landtile );
00501           if ( ~lt_flags & USTRUCT_TILE::FLAG_BLOCKING )
00502           { // this seems to be the default.
00503             lt_flags |= USTRUCT_TILE::FLAG_PLATFORM;
00504           }
00505           lt_flags |= USTRUCT_TILE::FLAG_NO_SHOOT;    // added to make sure people using noshoot will have shapes
00506           // generated by this tile in future block LOS, shouldn't
00507           // affect people using old LOS method one way or another.
00508           lt_flags |= USTRUCT_TILE::FLAG_FLOOR;
00509           lt_flags |= USTRUCT_TILE::FLAG_HALF_HEIGHT; // the entire map is this way
00510 
00511           if ( lt_flags & USTRUCT_TILE::FLAG_WALL )
00512             lt_height = 20;
00513 
00514           readstatics( statics, x, y,
00515                        USTRUCT_TILE::FLAG_BLOCKING |
00516                        USTRUCT_TILE::FLAG_PLATFORM |
00517                        USTRUCT_TILE::FLAG_HALF_HEIGHT |
00518                        USTRUCT_TILE::FLAG_LIQUID |
00519                        USTRUCT_TILE::FLAG_HOVEROVER
00520                        //USTRUCT_TILE::FLAG__WALK
00521                        );
00522 
00523           for ( unsigned i = 0; i < statics.size(); ++i )
00524           {
00525             StaticRec srec = statics[i];
00526 
00527             unsigned int polflags = polflags_from_tileflags( srec.graphic, srec.flags, cfg_use_no_shoot, cfg_LOS_through_windows );
00528 
00529             if ( ( ~polflags & FLAG::MOVELAND ) &&
00530                  ( ~polflags & FLAG::MOVESEA ) &&
00531                  ( ~polflags & FLAG::BLOCKSIGHT ) &&
00532                  ( ~polflags & FLAG::BLOCKING ) &&
00533                  ( ~polflags & FLAG::OVERFLIGHT ) )
00534             {
00535               // remove it.  we'll re-sort later.
00536               statics.erase( statics.begin() + i );
00537               --i; // do-over
00538             }
00539             if ( ( ~srec.flags & USTRUCT_TILE::FLAG_BLOCKING ) &&
00540                  ( ~srec.flags & USTRUCT_TILE::FLAG_PLATFORM ) &&
00541                  ( ~srec.flags & USTRUCT_TILE::FLAG_HALF_HEIGHT ) &&
00542                  ( ~srec.flags & USTRUCT_TILE::FLAG_LIQUID ) &&
00543                  ( ~srec.flags & USTRUCT_TILE::FLAG_HOVEROVER ) )
00544                  /*(~srec.flags & USTRUCT_TILE::FLAG__WALK)*/
00545             {
00546               // remove it.  we'll re-sort later.
00547               statics.erase( statics.begin() + i );
00548               --i; // do-over
00549             }
00550           }
00551 
00552           bool addMap = true;
00553 
00554           for ( const auto &srec : statics )
00555           {
00556             // Look for water tiles.  If there are any, discard the map (which is usually at -15 anyway)
00557             if ( z + lt_height <= srec.z && ( ( srec.z - ( z + lt_height ) ) <= 10 ) && // only where the map is below or same Z as the static
00558                  srec.graphic >= 0x1796 && srec.graphic <= 0x17B2 ) // FIXME hardcoded
00559             {
00560               // arr, there be water here
00561               addMap = false;
00562             }
00563 
00564             // if there's a static on top of one of these "wall" landtiles, make it override.
00565             if ( ( lt_flags & USTRUCT_TILE::FLAG_WALL ) && // wall?
00566                  z <= srec.z &&
00567                  srec.z - z <= lt_height )
00568             {
00569 
00570               lt_height = srec.z - z;
00571             }
00572           }
00573           // shadows above caves
00574           if ( is_cave_shadow( mi ) && !statics.empty() )
00575           {
00576             addMap = false;
00577           }
00578 
00579 
00580 
00581           // If the map is a NODRAW tile, and there are statics, discard the map tile
00582           if ( mi.landtile == 2 && !statics.empty() )
00583             addMap = false;
00584 
00585           if ( addMap )
00586             statics.push_back( StaticRec( 0, static_cast<signed char>( z ), lt_flags, static_cast<char>( lt_height ) ) );
00587 
00588           sort( statics.begin(), statics.end(), StaticsByZ() );
00589           reverse( statics.begin(), statics.end() );
00590 
00591           std::vector<MapShape> shapes;
00592 
00593           // try to consolidate like shapes, and discard ones we don't care about.
00594           while ( !statics.empty() )
00595           {
00596             StaticRec srec = statics.back();
00597             statics.pop_back();
00598 
00599             unsigned int polflags = polflags_from_tileflags( srec.graphic, srec.flags, cfg_use_no_shoot, cfg_LOS_through_windows );
00600             if ( ( ~polflags & FLAG::MOVELAND ) &&
00601                  ( ~polflags & FLAG::MOVESEA ) &&
00602                  ( ~polflags & FLAG::BLOCKSIGHT ) &&
00603                  ( ~polflags & FLAG::BLOCKING ) &&
00604                  ( ~polflags & FLAG::OVERFLIGHT ) )
00605             {
00606               passert_always( 0 );
00607               continue;
00608             }
00609             if ( ( ~srec.flags & USTRUCT_TILE::FLAG_BLOCKING ) &&
00610                  ( ~srec.flags & USTRUCT_TILE::FLAG_PLATFORM ) &&
00611                  ( ~srec.flags & USTRUCT_TILE::FLAG_HALF_HEIGHT ) &&
00612                  ( ~srec.flags & USTRUCT_TILE::FLAG_LIQUID ) &&
00613                  ( ~srec.flags & USTRUCT_TILE::FLAG_HOVEROVER ) )
00614                  /*(~srec.flags & USTRUCT_TILE::FLAG__WALK)*/
00615             {
00616               passert_always( 0 );
00617               continue;
00618             }
00619 
00620             if ( shapes.empty() )
00621             {
00622               // this, whatever it is, is the map base.
00623               //TODO: look for water statics and use THOSE as the map.
00624               MapShape shape;
00625               shape.z = srec.z;      //these will be converted below to
00626               shape.height = 0;      //make the map "solid"
00627               shape.flags = static_cast<unsigned char>( polflags );
00628               // no matter what, the lowest level is gradual
00629               shape.flags |= FLAG::GRADUAL;
00630               shapes.push_back( shape );
00631 
00632               //for wall flag - map tile always height 0, at bottom. if map tile has height, add it as a static
00633               if ( srec.height != 0 )
00634               {
00635                 MapShape _shape;
00636                 _shape.z = srec.z;
00637                 _shape.height = srec.height;
00638                 _shape.flags = polflags;
00639                 shapes.push_back( _shape );
00640 
00641               }
00642               continue;
00643             }
00644 
00645             MapShape& prev = shapes.back();
00646             // we're adding it.
00647             MapShape shape;
00648             shape.z = srec.z;
00649             shape.height = srec.height;
00650             shape.flags = polflags;
00651 
00652             //always add the map shape seperately
00653             if ( shapes.size() == 1 )
00654             {
00655               shapes.push_back( shape );
00656               continue;
00657             }
00658 
00659             if ( shape.z < prev.z + prev.height )
00660             {
00661               // things can't exist in the same place.
00662               // shrink the bottom part of this shape.
00663               // if that would give it negative height, then skip it.
00664               short height_remove = prev.z + prev.height - shape.z;
00665               if ( height_remove <= shape.height )
00666               {
00667                 shape.z += height_remove;
00668                 shape.height -= height_remove;
00669               }
00670               else
00671               { // example: 5530, 14
00672                 continue;
00673               }
00674             }
00675 
00676             // sometimes water has "sand" a couple z-coords above it.
00677             // We'll try to detect this (really, anything that is up to 4 dist from water)
00678             // and extend the thing above downward.
00679             if ( ( prev.flags & FLAG::MOVESEA ) &&
00680                  ( shape.z > prev.z + prev.height ) &&
00681                  ( shape.z <= prev.z + prev.height + 4 ) )
00682             {
00683               short height_add = shape.z - prev.z - prev.height;
00684               shape.z -= height_add;
00685               shape.height += height_add;
00686             }
00687             if ( ( prev.flags & FLAG::MOVESEA ) &&
00688                  ( prev.z + prev.height == -5 ) &&
00689                  ( shape.flags & FLAG::MOVESEA ) &&
00690                  ( shape.z == 25 ) )
00691             {
00692               // oddly, there are some water tiles at z=25 in some places...I don't get it
00693               continue;
00694             }
00695 
00696             //string prevflags_s = flagstr(prev.flags);
00697             //const char* prevflags = prevflags_s.c_str();
00698             //string shapeflags_s = flagstr(shape.flags);
00699             //const char* shapeflags = shapeflags_s.c_str();
00700 
00701             if ( shape.z > prev.z + prev.height )
00702             {
00703               //
00704               // elevated above what's below, must include separately
00705               //
00706 
00707               shapes.push_back( shape );
00708               continue;
00709             }
00710 
00711             passert_always( shape.z == prev.z + prev.height );
00712 
00713             if ( shape.z == prev.z + prev.height )
00714             {
00715               //
00716               // sitting right on top of the previous solid
00717               //
00718 
00719               // standable atop non-standable: standable
00720               // nonstandable atop standable: nonstandable
00721               // etc
00722               bool can_combine = flags_match( prev.flags, shape.flags, FLAG::BLOCKSIGHT | FLAG::BLOCKING );
00723               if ( prev.flags & FLAG::MOVELAND &&
00724                    ~shape.flags & FLAG::BLOCKING &&
00725                    ~shape.flags & FLAG::MOVELAND )
00726               {
00727                 can_combine = false;
00728               }
00729 
00730               if ( can_combine )
00731               {
00732                 prev.flags = shape.flags;
00733                 prev.height += shape.height;
00734               }
00735               else // if one blocks LOS, but not the other, they can't be combined this way.
00736               {
00737                 shapes.push_back( shape );
00738                 continue;
00739               }
00740             }
00741           }
00742 
00743           // the first StaticShape is the map base.
00744           MapShape base = shapes[0];
00745           shapes.erase( shapes.begin() );
00746           MAPCELL cell;
00747           passert_always( base.height == 0 );
00748           cell.z = static_cast<signed char>( base.z ); //assume now map has height=1. a static was already added if it was >0
00749           cell.flags = static_cast<u8>( base.flags );
00750           if ( !shapes.empty() )
00751             cell.flags |= FLAG::MORE_SOLIDS;
00752 
00753           mapwriter.SetMapCell( x, y, cell );
00754 
00755           if ( !shapes.empty() )
00756           {
00757             ++with_more_solids;
00758             total_statics += static_cast<unsigned int>( shapes.size() );
00759             if ( idx2_offset == 0 )
00760               idx2_offset = mapwriter.NextSolidx2Offset();
00761 
00762             unsigned int addindex = mapwriter.NextSolidIndex() - idx2_elem.baseindex;
00763             if ( addindex > std::numeric_limits<unsigned short>::max() )
00764                 throw std::runtime_error("addoffset overflow");
00765             idx2_elem.addindex[x_add][y_add] = static_cast<unsigned short>( addindex );
00766             int count = static_cast<int>( shapes.size() );
00767             for ( int j = 0; j < count; ++j )
00768             {
00769               MapShape shape = shapes[j];
00770               char _z, height, flags;
00771               _z = static_cast<char>( shapes[j].z );
00772               height = static_cast<char>( shape.height );
00773               flags = static_cast<u8>( shape.flags );
00774               if ( !height )//make 0 height solid
00775               {
00776                 --_z;
00777                 ++height;
00778               }
00779 
00780               if ( j != count - 1 )
00781                 flags |= FLAG::MORE_SOLIDS;
00782               SOLIDS_ELEM solid;
00783               solid.z = _z;
00784               solid.height = height;
00785               solid.flags = flags;
00786               mapwriter.AppendSolid( solid );
00787             }
00788           }
00789         }
00790       }
00791       if ( idx2_offset )
00792       {
00793         ++nonempty;
00794         mapwriter.AppendSolidx2Elem( idx2_elem );
00795       }
00796       else
00797       {
00798         ++empty;
00799       }
00800       mapwriter.SetSolidx2Offset( x_base, y_base, idx2_offset );
00801     }
00802 
00803     void write_multi( FILE* multis_cfg, unsigned id, FILE* multi_mul, unsigned int offset, unsigned int length )
00804     {
00805       USTRUCT_MULTI_ELEMENT elem;
00806       unsigned int count;
00807       if ( cfg_use_new_hsa_format )
00808         count = length / sizeof( USTRUCT_MULTI_ELEMENT_HSA );
00809       else
00810         count = length / sizeof elem;
00811 
00812       std::string type, mytype;
00813       if ( BoatTypes.count( id ) )
00814         type = "Boat";
00815       else if ( HouseTypes.count( id ) )
00816         type = "House";
00817       else if ( StairTypes.count( id ) )
00818         type = "Stairs";
00819       else
00820       {
00821         ERROR_PRINT << "Type 0x" << fmt::hexu( id ) << " not found in uoconvert.cfg, assuming \"House\" type.\n";
00822         type = "House";
00823       }
00824       mytype = type;
00825 
00826       fprintf( multis_cfg, "%s 0x%x\n", type.c_str(), id );
00827       fprintf( multis_cfg, "{\n" );
00828 
00829       if (fseek(multi_mul, offset, SEEK_SET) != 0)
00830       {
00831           throw std::runtime_error("write_multi(): fseek() failed");
00832       }
00833 
00834 
00835       bool first = true;
00836       while ( count-- )
00837       {
00838           if (fread(&elem, sizeof elem, 1, multi_mul) != 1) {
00839               throw std::runtime_error("write_multi(): fread() failed");
00840           }
00841 
00842           if (cfg_use_new_hsa_format) {
00843               if (fseek(multi_mul, 4, SEEK_CUR) != 0)
00844                   throw std::runtime_error("write_multi(): fseek() failed");
00845           }
00846 
00847         if ( elem.graphic == GRAPHIC_NODRAW )
00848           continue;
00849 
00850         if ( elem.flags )
00851           type = "static";
00852         else
00853           type = "dynamic";
00854 
00855         // boats typically have as their first element the "mast", but flagged as dynamic.
00856         if ( mytype == "Boat" )
00857         {
00858           if ( first && elem.graphic != 1 )
00859             type = "static";
00860         }
00861         std::string comment;
00862         if ( cfg_use_new_hsa_format )
00863         {
00864           USTRUCT_TILE_HSA tile;
00865           readtile( elem.graphic, &tile );
00866           comment.assign( tile.name, sizeof( tile.name ) );
00867         }
00868         else
00869         {
00870           USTRUCT_TILE tile;
00871           readtile( elem.graphic, &tile );
00872           comment.assign( tile.name, sizeof( tile.name ) );
00873         }
00874         fprintf( multis_cfg, "    %-7s 0x%04x %4d %4d %4d   // %s\n", type.c_str(), elem.graphic, elem.x, elem.y, elem.z, comment.c_str() );
00875         first = false;
00876       }
00877       fprintf( multis_cfg, "}\n" );
00878       fprintf( multis_cfg, "\n" );
00879     }
00880 
00881     void create_multis_cfg( FILE* multi_idx, FILE* multi_mul, FILE* multis_cfg )
00882     {
00883       if ( fseek( multi_idx, 0, SEEK_SET ) != 0 )
00884           throw std::runtime_error("create_multis_cfg: fseek failed");
00885       unsigned count = 0;
00886       USTRUCT_IDX idxrec;
00887       for ( int i = 0; fread( &idxrec, sizeof idxrec, 1, multi_idx ) == 1; ++i )
00888       {
00889         const USTRUCT_VERSION* vrec = NULL;
00890 
00891         if ( check_verdata( VERFILE_MULTI_MUL, i, vrec ) )
00892         {
00893           write_multi( multis_cfg, i, verfile, vrec->filepos, vrec->length );
00894           ++count;
00895         }
00896         else
00897         {
00898           if ( idxrec.offset == 0xFFffFFffLu )
00899             continue;
00900 
00901           write_multi( multis_cfg, i, multi_mul, idxrec.offset, idxrec.length );
00902           ++count;
00903         }
00904       }
00905       INFO_PRINT << count << " multi definitions written to multis.cfg\n";
00906     }
00907 
00908     void create_multis_cfg()
00909     {
00910       FILE *multi_idx = open_uo_file( "multi.idx" );
00911       FILE *multi_mul = open_uo_file( "multi.mul" );
00912 
00913       FILE* multis_cfg = fopen( "multis.cfg", "wt" );
00914 
00915       create_multis_cfg( multi_idx, multi_mul, multis_cfg );
00916 
00917       fclose( multis_cfg );
00918 
00919       fclose( multi_idx );
00920       fclose( multi_mul );
00921     }
00922     void write_flags( FILE* fp, unsigned int flags )
00923     {
00924       if ( flags & FLAG::MOVELAND )    fprintf( fp, "    MoveLand 1\n" );
00925       if ( flags & FLAG::MOVESEA )     fprintf( fp, "    MoveSea 1\n" );
00926       if ( flags & FLAG::BLOCKSIGHT )  fprintf( fp, "    BlockSight 1\n" );
00927       if ( ~flags & FLAG::OVERFLIGHT ) fprintf( fp, "    OverFlight 0\n" );
00928       if ( flags & FLAG::ALLOWDROPON ) fprintf( fp, "    AllowDropOn 1\n" );
00929       if ( flags & FLAG::GRADUAL )     fprintf( fp, "    Gradual 1\n" );
00930       if ( flags & FLAG::STACKABLE )   fprintf( fp, "    Stackable 1\n" );
00931       if ( flags & FLAG::BLOCKING )    fprintf( fp, "    Blocking 1\n" );
00932       if ( flags & FLAG::MOVABLE )     fprintf( fp, "    Movable 1\n" );
00933       if ( flags & FLAG::EQUIPPABLE )  fprintf( fp, "    Equippable 1\n" );
00934       if ( flags & FLAG::DESC_PREPEND_A ) fprintf( fp, "    DescPrependA 1\n" );
00935       if ( flags & FLAG::DESC_PREPEND_AN ) fprintf( fp, "    DescPrependAn 1\n" );
00936     }
00937 
00938     void create_tiles_cfg()
00939     {
00940       FILE* fp = fopen( "tiles.cfg", "wt" );
00941       int mountCount;
00942       char name[21];
00943 
00944       unsigned count = 0;
00945       for ( unsigned int graphic_i = 0; graphic_i <= Plib::systemstate.config.max_tile_id; ++graphic_i )
00946       {
00947         u16 graphic = static_cast<u16>( graphic_i );
00948         USTRUCT_TILE tile;
00949         if ( cfg_use_new_hsa_format )
00950         {
00951           USTRUCT_TILE_HSA newtile;
00952           read_objinfo( graphic, newtile );
00953           tile.anim = newtile.anim;
00954           tile.flags = newtile.flags;
00955           tile.height = newtile.height;
00956           tile.layer = newtile.layer;
00957           memcpy( tile.name, newtile.name, sizeof tile.name );
00958           tile.unk14 = newtile.unk14;
00959           tile.unk15 = newtile.unk15;
00960           tile.unk6 = newtile.unk6;
00961           tile.unk7 = newtile.unk7;
00962           tile.unk8 = newtile.unk8;
00963           tile.unk9 = newtile.unk9;
00964           tile.weight = newtile.weight;
00965         }
00966         else
00967           read_objinfo( graphic, tile );
00968         mountCount = static_cast<int>( MountTypes.count( graphic ) );
00969 
00970         if ( tile.name[0] == '\0' &&
00971              tile.flags == 0 &&
00972              tile.layer == 0 &&
00973              tile.height == 0 &&
00974              mountCount == 0
00975              )
00976         {
00977           continue;
00978         }
00979         unsigned int flags = polflags_from_tileflags( graphic, tile.flags, cfg_use_no_shoot, cfg_LOS_through_windows );
00980         if ( mountCount != 0 )
00981         {
00982           tile.layer = 25;
00983           flags |= FLAG::EQUIPPABLE;
00984         }
00985 
00986         memset( name, 0, sizeof name );
00987         memcpy( name, tile.name, sizeof tile.name );
00988 
00989         fprintf( fp, "tile 0x%x\n", graphic );
00990         fprintf( fp, "{\n" );
00991         fprintf( fp, "    Desc %s\n", name );
00992         fprintf( fp, "    UoFlags 0x%08lx\n", static_cast<unsigned long>( tile.flags ) );
00993         if ( tile.layer )
00994           fprintf( fp, "    Layer %u\n", tile.layer );
00995         fprintf( fp, "    Height %u\n", tile.height );
00996         fprintf( fp, "    Weight %u\n", tile.weight );
00997         write_flags( fp, flags );
00998         fprintf( fp, "}\n" );
00999         fprintf( fp, "\n" );
01000         ++count;
01001       }
01002       fclose( fp );
01003 
01004       INFO_PRINT << count << " tile definitions written to tiles.cfg\n";
01005     }
01006 
01007     void create_landtiles_cfg()
01008     {
01009       FILE* fp = fopen( "landtiles.cfg", "wt" );
01010       unsigned count = 0;
01011 
01012       for ( u16 i = 0; i <= 0x3FFF; ++i )
01013       {
01014         USTRUCT_LAND_TILE landtile;
01015         if ( cfg_use_new_hsa_format )
01016         {
01017           USTRUCT_LAND_TILE_HSA newlandtile;
01018           readlandtile( i, &newlandtile );
01019           landtile.flags = newlandtile.flags;
01020           landtile.unk = newlandtile.unk;
01021           memcpy( landtile.name, newlandtile.name, sizeof landtile.name );
01022         }
01023         else
01024           readlandtile( i, &landtile );
01025 
01026         if ( landtile.name[0] || landtile.flags )
01027         {
01028           fprintf( fp, "landtile 0x%x\n", i );
01029           fprintf( fp, "{\n" );
01030           fprintf( fp, "    Name %s\n", landtile.name );
01031           fprintf( fp, "    UoFlags 0x%08lx\n", static_cast<unsigned long>( landtile.flags ) );
01032 
01033           unsigned int flags = polflags_from_landtileflags( i, landtile.flags );
01034           flags &= ~FLAG::MOVABLE; // movable makes no sense for landtiles
01035           write_flags( fp, flags );
01036           fprintf( fp, "}\n" );
01037           fprintf( fp, "\n" );
01038           ++count;
01039         }
01040       }
01041       fclose( fp );
01042 
01043       INFO_PRINT << count << " landtile definitions written to landtiles.cfg\n";
01044     }
01045   }
01046 
01047   int xmain( int argc, char* argv[] )
01048   {
01049 
01050     Clib::StoreCmdArgs( argc, argv );
01051     Plib::systemstate.config.max_tile_id = UOBJ_DEFAULT_MAX; //default
01052 
01053     if ( Clib::FindArg2( "uodata=" ) != NULL )
01054     {
01055       Plib::systemstate.config.uo_datafile_root = Clib::FindArg2( "uodata=" );
01056       Plib::systemstate.config.uo_datafile_root = Clib::normalized_dir_form( Plib::systemstate.config.uo_datafile_root );
01057     }
01058     else
01059     {
01060       INFO_PRINT << "Reading pol.cfg.\n";
01061       Clib::ConfigFile cf( "pol.cfg" );
01062       Clib::ConfigElem elem;
01063 
01064       cf.readraw( elem );
01065       Plib::systemstate.config.uo_datafile_root = elem.remove_string( "UoDataFileRoot" );
01066       Plib::systemstate.config.uo_datafile_root = Clib::normalized_dir_form( Plib::systemstate.config.uo_datafile_root );
01067 
01068       unsigned short max_tile = elem.remove_ushort( "MaxTileID", UOBJ_DEFAULT_MAX );
01069 
01070       if ( max_tile == UOBJ_DEFAULT_MAX || max_tile == UOBJ_SA_MAX || max_tile == UOBJ_HSA_MAX )
01071         Plib::systemstate.config.max_tile_id = max_tile;
01072     }
01073 
01074     if ( Clib::FindArg2( "maxtileid=" ) != NULL )
01075     {
01076       unsigned short max_tile = static_cast<unsigned short>( Clib::LongHexArg2( "maxtileid=", UOBJ_DEFAULT_MAX ) );
01077       if ( max_tile == UOBJ_DEFAULT_MAX || max_tile == UOBJ_SA_MAX || max_tile == UOBJ_HSA_MAX )
01078         Plib::systemstate.config.max_tile_id = max_tile;
01079     }
01080 
01081 
01082     std::string main_cfg = "uoconvert.cfg";
01083     if ( Clib::FileExists( main_cfg.c_str( ) ) )
01084     {
01085       std::string temp;
01086       Clib::ConfigElem elem;
01087       INFO_PRINT << "Reading uoconvert.cfg.\n";
01088       Clib::ConfigFile cf_main( main_cfg.c_str( ) );
01089       while ( cf_main.read( elem ) )
01090       {
01091         if ( elem.type_is( "MultiTypes" ) )
01092         {
01093           temp = elem.remove_string( "Boats" );
01094           ISTRINGSTREAM is_boats( temp );
01095           std::string graphicnum;
01096           while ( is_boats >> graphicnum )
01097             UOConvert::BoatTypes.insert( strtoul( graphicnum.c_str( ), NULL, 0 ) );
01098 
01099           temp = elem.remove_string( "Houses" );
01100           ISTRINGSTREAM is_houses( temp );
01101           while ( is_houses >> graphicnum )
01102             UOConvert::HouseTypes.insert( strtoul( graphicnum.c_str( ), NULL, 0 ) );
01103 
01104           temp = elem.remove_string( "Stairs" );
01105           ISTRINGSTREAM is_stairs( temp );
01106           while ( is_stairs >> graphicnum )
01107             UOConvert::StairTypes.insert( strtoul( graphicnum.c_str( ), NULL, 0 ) );
01108         }
01109         else if ( elem.type_is( "LOSOptions" ) )
01110         {
01111           if ( elem.has_prop( "UseNoShoot" ) )
01112             UOConvert::cfg_use_no_shoot = elem.remove_bool( "UseNoShoot" );
01113 
01114           if ( elem.has_prop( "LOSThroughWindows" ) )
01115             UOConvert::cfg_LOS_through_windows = elem.remove_bool( "LOSThroughWindows" );
01116         }
01117         else if ( elem.type_is( "Mounts" ) )
01118         {
01119           std::string graphicnum;
01120           temp = elem.remove_string( "Tiles" );
01121           ISTRINGSTREAM is_mounts( temp );
01122           while ( is_mounts >> graphicnum )
01123           {
01124             UOConvert::MountTypes.insert( strtoul( graphicnum.c_str( ), NULL, 0 ) );
01125           }
01126         }
01127         else if ( elem.type_is( "StaticOptions" ) )
01128         {
01129           if ( elem.has_prop( "MaxStaticsPerBlock" ) )
01130           {
01131             UOConvert::cfg_max_statics_per_block = elem.remove_int( "MaxStaticsPerBlock" );
01132 
01133             if ( UOConvert::cfg_max_statics_per_block > MAX_STATICS_PER_BLOCK )
01134             {
01135               UOConvert::cfg_max_statics_per_block = MAX_STATICS_PER_BLOCK;
01136               INFO_PRINT << "max. Statics per Block limited to " << UOConvert::cfg_max_statics_per_block << " Items\n";
01137             }
01138             else if ( UOConvert::cfg_max_statics_per_block < 0 )
01139               UOConvert::cfg_max_statics_per_block = 1000;
01140           }
01141 
01142           if ( elem.has_prop( "WarningStaticsPerBlock" ) )
01143           {
01144             UOConvert::cfg_warning_statics_per_block = elem.remove_int( "WarningStaticsPerBlock" );
01145 
01146             if ( UOConvert::cfg_warning_statics_per_block > MAX_STATICS_PER_BLOCK )
01147             {
01148               UOConvert::cfg_warning_statics_per_block = MAX_STATICS_PER_BLOCK;
01149               INFO_PRINT << "max. Statics per Block for Warning limited to "
01150                 << UOConvert::cfg_warning_statics_per_block << " Items\n";
01151             }
01152             else if ( UOConvert::cfg_warning_statics_per_block < 0 )
01153               UOConvert::cfg_warning_statics_per_block = 1000;
01154           }
01155 
01156           if ( elem.has_prop( "ShowIllegalGraphicWarning" ) )
01157             UOConvert::cfg_show_illegal_graphic_warning = elem.remove_bool( "ShowIllegalGraphicWarning" );
01158         }
01159         else if ( elem.type_is( "TileOptions" ) )
01160         {
01161           if ( elem.has_prop( "ShowRoofAndPlatformWarning" ) )
01162             Core::cfg_show_roof_and_platform_warning = elem.remove_bool( "ShowRoofAndPlatformWarning" );
01163         }
01164         else if ( elem.type_is( "ClientOptions" ) )
01165         {
01166           if ( elem.has_prop( "UseNewHSAFormat" ) )
01167             UOConvert::cfg_use_new_hsa_format = elem.remove_bool( "UseNewHSAFormat" );
01168         }
01169       }
01170     }
01171 
01172     std::string command = "map";
01173     if ( argc > 1 )
01174     {
01175       command = argv[1];
01176       ++argv;
01177       --argc;
01178     }
01179 
01180     if ( command == "map" )
01181     {
01182       UOConvert::uo_mapid = Clib::LongArg2( "mapid=", 0 );
01183       UOConvert::uo_usedif = Clib::LongArg2( "usedif=", 0 );
01184 
01185       const char* realm = Clib::FindArg2( "realm=", "britannia" );
01186       int default_width = 6144;
01187       int default_height = 4096;
01188       switch ( UOConvert::uo_mapid )
01189       {
01190         case 0:
01191         case 1:
01192           break;
01193         case 2: // ilshenar:
01194           default_width = 2304;
01195           default_height = 1600;
01196           break;
01197         case 3: // malas
01198           default_width = 2560;
01199           default_height = 2048;
01200           break;
01201         case 4: // tokuno
01202           default_width = 1448;
01203           default_height = 1448;
01204           break;
01205         case 5: // termur
01206           default_width = 1280;
01207           default_height = 4096;
01208           break;
01209       }
01210       int width = Clib::LongArg2( "width=", default_width );
01211       int height = Clib::LongArg2( "height=", default_height );
01212       UOConvert::uo_map_width = static_cast<unsigned short>( width );
01213       UOConvert::uo_map_height = static_cast<unsigned short>( height );
01214 
01215       UOConvert::open_uo_data_files( );
01216       UOConvert::read_uo_data( );
01217 
01218       int x = Clib::LongArg2( "x=", -1 );
01219       int y = Clib::LongArg2( "y=", -1 );
01220 
01221       // brittania: realm=main mapid=0 width=6144 height=4096
01222       // ilshenar: realm=ilshenar mapid=2 width=2304 height=1600
01223       // malas: realm=malas mapid=3 width=2560 height=2048
01224       // tokuno: realm=tokuno mapid=4 width=1448 height=1448
01225       // termur: realm=termur mapid=5 width=1280 height=4096
01226 
01227       if ( x >= 0 && y >= 0 )
01228       {
01229         UOConvert::update_map( realm, static_cast<u16>( x ), static_cast<u16>( y ) );
01230       }
01231       else
01232       {
01233         UOConvert::create_map( realm, static_cast<unsigned short>( width ), static_cast<unsigned short>( height ) );
01234       }
01235     }
01236     else if ( command == "statics" )
01237     {
01238       const char* realm = Clib::FindArg2( "realm=", "britannia" );
01239       Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realm );
01240 
01241       UOConvert::uo_mapid = descriptor.uomapid;
01242       UOConvert::uo_usedif = descriptor.uodif;
01243       UOConvert::uo_map_width = static_cast<unsigned short>( descriptor.width );
01244       UOConvert::uo_map_height = static_cast<unsigned short>( descriptor.height );
01245 
01246       UOConvert::open_uo_data_files( );
01247       UOConvert::read_uo_data( );
01248 
01249       Core::write_pol_static_files( realm );
01250     }
01251     else if ( command == "multis" )
01252     {
01253       UOConvert::open_uo_data_files( );
01254       UOConvert::read_uo_data( );
01255       UOConvert::create_multis_cfg( );
01256     }
01257     else if ( command == "tiles" )
01258     {
01259       UOConvert::open_uo_data_files( );
01260       UOConvert::read_uo_data( );
01261       UOConvert::create_tiles_cfg( );
01262     }
01263     else if ( command == "landtiles" )
01264     {
01265       UOConvert::open_uo_data_files( );
01266       UOConvert::read_uo_data( );
01267       UOConvert::create_landtiles_cfg( );
01268     }
01269     else if ( command == "maptile" )
01270     {
01271       const char* realm = Clib::FindArg2( "realm=", "britannia" );
01272       Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realm );
01273 
01274       UOConvert::uo_mapid = descriptor.uomapid;
01275       UOConvert::uo_usedif = descriptor.uodif;
01276       UOConvert::uo_map_width = static_cast<unsigned short>( descriptor.width );
01277       UOConvert::uo_map_height = static_cast<unsigned short>( descriptor.height );
01278 
01279       UOConvert::open_uo_data_files( );
01280       UOConvert::read_uo_data( );
01281 
01282       UOConvert::create_maptile( realm );
01283     }
01284     else if ( command == "flags" )
01285     {
01286       UOConvert::display_flags( );
01287     }
01288     else
01289     {
01290       ERROR_PRINT << "Usage: uoconvert [command] [options]\n"
01291         << "Commands: \n"
01292         << "  map {uodata=Dir} {maxtileid=0x3FFF/0x7FFF} {realm=realmname} {width=Width} {height=Height} {x=X} {y=Y}\n"
01293         << "  statics {uodata=Dir} {maxtileid=0x3FFF/0x7FFF} {realm=realmname}\n"
01294         << "  maptile {uodata=Dir} {maxtileid=0x3FFF/0x7FFF} {realm=realmname}\n"
01295         << "  multis {uodata=Dir} {maxtileid=0x3FFF/0x7FFF}\n"
01296         << "  tiles {uodata=Dir} {maxtileid=0x3FFF/0x7FFF}\n"
01297         << "  landtiles {uodata=Dir} {maxtileid=0x3FFF/0x7FFF}\n";
01298       return 1;
01299     }
01300     UOConvert::clear_tiledata( );
01301     return 0;
01302   }
01303 
01304 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines