|
Pol
Revision:e09f183
|
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 }