|
Pol
Revision:b38175a
|
00001 /* 00002 History 00003 ======= 00004 2009/09/03 MuadDib: Relocation of multi related cpp/h 00005 2009/11/23 Turley: added staticdefrag to defrag/remove duplicate statics 00006 2009/12/02 Turley: added config.max_tile_id - Tomi 00007 00008 Notes 00009 ======= 00010 00011 */ 00012 00013 #include "../pol/uofile.h" 00014 #include "../pol/polcfg.h" 00015 #include "../pol/polfile.h" 00016 #include "../pol/uofilei.h" 00017 #include "../pol/multi/multidef.h" 00018 #include "../pol/globals/multidefs.h" 00019 #include "../pol/objtype.h" 00020 #include "../pol/poltype.h" 00021 00022 #include "../plib/realmdescriptor.h" 00023 #include "../plib/staticblock.h" 00024 #include "../plib/systemstate.h" 00025 00026 #include "../clib/strutil.h" 00027 #include "../clib/stlutil.h" 00028 00029 #include "../clib/cfgelem.h" 00030 #include "../clib/cfgfile.h" 00031 #include "../clib/cmdargs.h" 00032 #include "../clib/fileutil.h" 00033 #include "../clib/logfacility.h" 00034 #include "../clib/fdump.h" 00035 #include "../clib/passert.h" 00036 00037 #ifdef _MSC_VER 00038 #pragma warning(disable:4996) // deprecation warning for fopen, sprintf, stricmp 00039 #endif 00040 00041 namespace Pol { 00042 namespace Multi { 00043 void read_multidefs(); 00044 bool BoatShapeExists( unsigned short /*graphic*/ ) 00045 { 00046 return true; 00047 } 00048 } 00049 namespace Core { 00050 void safe_getmapinfo( unsigned short x, unsigned short y, short* z, USTRUCT_MAPINFO* mi ); 00051 void staticsmax(); 00052 void readwater(); 00053 } 00054 namespace Uotool { 00055 00056 int keyid[] = { 00057 0x0002, 0x01f5, 0x0226, 0x0347, 0x0757, 0x0286, 0x03b6, 0x0327, 00058 0x0e08, 0x0628, 0x0567, 0x0798, 0x19d9, 0x0978, 0x02a6, 0x0577, 00059 0x0718, 0x05b8, 0x1cc9, 0x0a78, 0x0257, 0x04f7, 0x0668, 0x07d8, 00060 0x1919, 0x1ce9, 0x03f7, 0x0909, 0x0598, 0x07b8, 0x0918, 0x0c68, 00061 0x02d6, 0x1869, 0x06f8, 0x0939, 0x1cca, 0x05a8, 0x1aea, 0x1c0a, 00062 0x1489, 0x14a9, 0x0829, 0x19fa, 0x1719, 0x1209, 0x0e79, 0x1f3a, 00063 0x14b9, 0x1009, 0x1909, 0x0136, 0x1619, 0x1259, 0x1339, 0x1959, 00064 0x1739, 0x1ca9, 0x0869, 0x1e99, 0x0db9, 0x1ec9, 0x08b9, 0x0859, 00065 0x00a5, 0x0968, 0x09c8, 0x1c39, 0x19c9, 0x08f9, 0x18f9, 0x0919, 00066 0x0879, 0x0c69, 0x1779, 0x0899, 0x0d69, 0x08c9, 0x1ee9, 0x1eb9, 00067 0x0849, 0x1649, 0x1759, 0x1cd9, 0x05e8, 0x0889, 0x12b9, 0x1729, 00068 0x10a9, 0x08d9, 0x13a9, 0x11c9, 0x1e1a, 0x1e0a, 0x1879, 0x1dca, 00069 0x1dfa, 0x0747, 0x19f9, 0x08d8, 0x0e48, 0x0797, 0x0ea9, 0x0e19, 00070 0x0408, 0x0417, 0x10b9, 0x0b09, 0x06a8, 0x0c18, 0x0717, 0x0787, 00071 0x0b18, 0x14c9, 0x0437, 0x0768, 0x0667, 0x04d7, 0x08a9, 0x02f6, 00072 0x0c98, 0x0ce9, 0x1499, 0x1609, 0x1baa, 0x19ea, 0x39fa, 0x0e59, 00073 0x1949, 0x1849, 0x1269, 0x0307, 0x06c8, 0x1219, 0x1e89, 0x1c1a, 00074 0x11da, 0x163a, 0x385a, 0x3dba, 0x17da, 0x106a, 0x397a, 0x24ea, 00075 0x02e7, 0x0988, 0x33ca, 0x32ea, 0x1e9a, 0x0bf9, 0x3dfa, 0x1dda, 00076 0x32da, 0x2eda, 0x30ba, 0x107a, 0x2e8a, 0x3dea, 0x125a, 0x1e8a, 00077 0x0e99, 0x1cda, 0x1b5a, 0x1659, 0x232a, 0x2e1a, 0x3aeb, 0x3c6b, 00078 0x3e2b, 0x205a, 0x29aa, 0x248a, 0x2cda, 0x23ba, 0x3c5b, 0x251a, 00079 0x2e9a, 0x252a, 0x1ea9, 0x3a0b, 0x391b, 0x23ca, 0x392b, 0x3d5b, 00080 0x233a, 0x2cca, 0x390b, 0x1bba, 0x3a1b, 0x3c4b, 0x211a, 0x203a, 00081 0x12a9, 0x231a, 0x3e0b, 0x29ba, 0x3d7b, 0x202a, 0x3adb, 0x213a, 00082 0x253a, 0x32ca, 0x23da, 0x23fa, 0x32fa, 0x11ca, 0x384a, 0x31ca, 00083 0x17ca, 0x30aa, 0x2e0a, 0x276a, 0x250a, 0x3e3b, 0x396a, 0x18fa, 00084 0x204a, 0x206a, 0x230a, 0x265a, 0x212a, 0x23ea, 0x3acb, 0x393b, 00085 0x3e1b, 0x1dea, 0x3d6b, 0x31da, 0x3e5b, 0x3e4b, 0x207a, 0x3c7b, 00086 0x277a, 0x3d4b, 0x0c08, 0x162a, 0x3daa, 0x124a, 0x1b4a, 0x264a, 00087 0x33da, 0x1d1a, 0x1afa, 0x39ea, 0x24fa, 0x373b, 0x249a, 0x372b, 00088 0x1679, 0x210a, 0x23aa, 0x1b8a, 0x3afb, 0x18ea, 0x2eca, 0x0627, 00089 0x00d4 // terminator 00090 }; 00091 00092 /* transforms table above into: 00093 { nbits, bits_reversed [[ LSB .. MSB ]] }, 00094 */ 00095 int print_ctable() 00096 { 00097 INFO_PRINT << "#include \"ctable.h\"\n\n" 00098 << "SVR_KEYDESC keydesc[ 257 ] = {\n"; 00099 fmt::Writer _tmp; 00100 for ( int i = 0; i <= 256; i++ ) 00101 { 00102 int nbits = keyid[i] & 0x0F; 00103 unsigned short inmask = 0x10; 00104 const unsigned short val = static_cast<const unsigned short>( keyid[i] ); 00105 unsigned short valout = 0; 00106 while ( nbits-- ) 00107 { 00108 valout <<= 1; 00109 if ( val & inmask ) 00110 valout |= 1; 00111 inmask <<= 1; 00112 } 00113 _tmp.Format( " {{ {:>2}, 0x{:04X}, 0x{:04X}}},\n" ) 00114 << ( keyid[i] & 0x0F ) 00115 << ( keyid[i] >> 4 ) 00116 << valout; 00117 } 00118 _tmp << "};\n"; 00119 INFO_PRINT << _tmp.str(); 00120 return 0; 00121 } 00122 00123 unsigned char buffer[10000]; 00124 00125 int Usage( int ret ) 00126 { 00127 ERROR_PRINT << "Usage: uotool func [params ...]\n" 00128 << " Functions:\n" 00129 << " tiledump filename Dump object information\n" 00130 << " vertile Dump updated object info\n" 00131 << " rawdump filename hdrlen reclen\n" 00132 << " ctable Print Server encryption table\n" 00133 << " findgraphic graphic finds coords of statics with graphic\n" 00134 << " findlandtileflags flags finds landtiles with flags\n" 00135 << " contour write binary file 6144x4096 z heights\n" 00136 << " mapdump x1 y1 [x2 y2] dumps map+statics info to html tables\n" 00137 << " landtileflagsearch flags [notflags] prints landtiles matching args\n" 00138 << " flagsearch flags [notflags] prints tiles matching flags\n" 00139 << " landtilehist prints landtile histogram\n" 00140 << " staticshist histogram of number of statics at a location\n" 00141 << " zhist histogram of map z\n" 00142 << " multis prints multi definitions \n" 00143 << " verdata prints verdata info\n" 00144 << " statics prints statics info\n" 00145 << " sndlist prints sound list info\n" 00146 << " verlandtile prints verdata landtile info\n" 00147 << " loschange prints differences in LOS handling \n" 00148 << " staticdefrag [realm] recreates static files {default britannia} \n" 00149 << " formatdesc name prints plural and singular form of name \n" 00150 << " checkmultis prints infos about multi center items \n"; 00151 return ret; 00152 } 00153 #define TILES_START 0x68800 00154 00155 void display_tileinfo( unsigned short objtype, const Core::USTRUCT_TILE& tile ) 00156 { 00157 fmt::Writer _tmp; 00158 _tmp.Format( "objtype: 0x{:04X}\n" ) << objtype; 00159 _tmp << " name: " << tile.name << "\n"; 00160 if ( tile.flags ) _tmp.Format( " flags: 0x{:08X}\n" ) << static_cast<unsigned long>( tile.flags ); 00161 if ( tile.weight ) _tmp.Format( " weight: 0x{:02X}\n" ) << (int)tile.weight; 00162 if ( tile.layer ) _tmp.Format( " layer: 0x{:02X}\n" ) << (int)tile.layer; 00163 if ( tile.unk6 ) _tmp.Format( " unk6: 0x{:02X}\n" ) << (int)tile.unk6; 00164 if ( tile.unk7 ) _tmp.Format( " unk7: 0x{:02X}\n" ) << (int)tile.unk7; 00165 if ( tile.unk8 ) _tmp.Format( " unk8: 0x{:02X}\n" ) << (int)tile.unk8; 00166 if ( tile.unk9 ) _tmp.Format( " unk9: 0x{:02X}\n" ) << (int)tile.unk9; 00167 if ( tile.anim ) _tmp.Format( " anim: 0x{:08X}\n" ) << static_cast<unsigned long>( tile.anim ); 00168 if ( tile.height ) _tmp.Format( " height: 0x{:02X}\n" ) << (int)tile.height; 00169 if ( tile.unk14 ) _tmp.Format( " unk14: 0x{:02X}\n" ) << (int)tile.unk14; 00170 if ( tile.unk15 ) _tmp.Format( " unk15: 0x{:02X}\n" ) << (int)tile.unk15; 00171 } 00172 00173 int tiledump( int argc, char **argv ) 00174 { 00175 Core::USTRUCT_TILE tile; 00176 u32 version; 00177 if ( argc != 3 ) 00178 return Usage( 1 ); 00179 00180 FILE *fp = fopen( argv[2], "rb" ); 00181 fseek( fp, TILES_START, SEEK_SET ); 00182 int recnum = 0; 00183 unsigned short objtype = 0; 00184 for ( ;; ) 00185 { 00186 if ( recnum == 0 ) 00187 { 00188 if ( fread( &version, sizeof version, 1, fp ) != 1 ) 00189 break; 00190 INFO_PRINT.Format( "Block Version: {:08X}\n" ) << static_cast<unsigned long>( version ); 00191 } 00192 if ( fread( &tile, sizeof tile, 1, fp ) != 1 ) 00193 break; 00194 display_tileinfo( objtype, tile ); 00195 00196 00197 ++objtype; 00198 ++recnum; 00199 if ( recnum == 32 ) 00200 recnum = 0; 00201 00202 } 00203 fclose( fp ); 00204 return 0; 00205 } 00206 00207 int vertile( int /*argc*/, char ** /*argv*/ ) 00208 { 00209 Core::USTRUCT_TILE tile; 00210 00211 Core::open_uo_data_files(); 00212 Core::read_uo_data( ); 00213 00214 int i; 00215 for ( i = 0; i <= 0xFFFF; i++ ) 00216 { 00217 unsigned short objtype = (unsigned short)i; 00218 read_objinfo( objtype, tile ); 00219 display_tileinfo( objtype, tile ); 00220 } 00221 Core::clear_tiledata( ); 00222 return 0; 00223 } 00224 00225 int verlandtile( int /*argc*/, char ** /*argv*/ ) 00226 { 00227 Core::USTRUCT_LAND_TILE landtile; 00228 00229 Core::open_uo_data_files( ); 00230 Core::read_uo_data( ); 00231 00232 int i; 00233 for ( i = 0; i <= 0x3FFF; i++ ) 00234 { 00235 unsigned short objtype = (unsigned short)i; 00236 readlandtile( objtype, &landtile ); 00237 if ( landtile.flags || landtile.unk || landtile.name[0] ) 00238 { 00239 INFO_PRINT << "Land Tile: 0x" << fmt::hexu(objtype) << "\n" 00240 << "\tflags: 0x" << fmt::hexu( landtile.flags ) << "\n" 00241 << "\t unk: 0x" << fmt::hexu( landtile.unk ) << "\n" 00242 << "\t name: " << landtile.name << "\n"; 00243 } 00244 } 00245 Core::clear_tiledata( ); 00246 return 0; 00247 } 00248 00249 int landtilehist( int /*argc*/, char** /*argv*/ ) 00250 { 00251 Core::USTRUCT_LAND_TILE landtile; 00252 00253 Core::open_uo_data_files( ); 00254 Core::read_uo_data( ); 00255 00256 typedef std::map<std::string, unsigned> M; 00257 M tilecount; 00258 00259 int i; 00260 for ( i = 0; i < 0x4000; i++ ) 00261 { 00262 unsigned short objtype = (unsigned short)i; 00263 readlandtile( objtype, &landtile ); 00264 tilecount[landtile.name] = tilecount[landtile.name] + 1; 00265 } 00266 00267 fmt::Writer tmp; 00268 for ( const auto &elem : tilecount ) 00269 { 00270 tmp << elem.first << ": " << elem.second << "\n"; 00271 } 00272 INFO_PRINT << tmp.str(); 00273 Core::clear_tiledata( ); 00274 return 0; 00275 } 00276 00277 int landtilecfg( int /*argc*/, char** /*argv*/ ) 00278 { 00279 Core::USTRUCT_LAND_TILE landtile; 00280 00281 Core::open_uo_data_files( ); 00282 Core::read_uo_data( ); 00283 00284 typedef std::map<std::string, unsigned> M; 00285 M tilecount; 00286 00287 int i; 00288 for ( i = 0; i < 0x4000; i++ ) 00289 { 00290 unsigned short objtype = (unsigned short)i; 00291 readlandtile( objtype, &landtile ); 00292 tilecount[landtile.name] = tilecount[landtile.name] + 1; 00293 } 00294 00295 fmt::Writer tmp; 00296 for ( const auto &elem : tilecount ) 00297 { 00298 tmp << elem.first << ": " << elem.second << "\n"; 00299 } 00300 INFO_PRINT << tmp.str(); 00301 Core::clear_tiledata( ); 00302 return 0; 00303 } 00304 00305 int flagsearch( int argc, char **argv ) 00306 { 00307 Core::USTRUCT_TILE tile; 00308 00309 Core::open_uo_data_files( ); 00310 Core::read_uo_data( ); 00311 00312 if ( argc < 3 ) return 1; 00313 00314 unsigned int flags = strtoul( argv[2], NULL, 0 ); 00315 unsigned int notflags = 0; 00316 if ( argc >= 4 ) 00317 notflags = strtoul( argv[3], NULL, 0 ); 00318 00319 int i; 00320 for ( i = 0; i <= 0xFFFF; i++ ) 00321 { 00322 unsigned short objtype = (unsigned short)i; 00323 read_objinfo( objtype, tile ); 00324 if ( ( ( tile.flags & flags ) == flags ) && 00325 ( ( ~tile.flags & notflags ) == notflags ) ) 00326 { 00327 display_tileinfo( objtype, tile ); 00328 } 00329 } 00330 Core::clear_tiledata( ); 00331 return 0; 00332 } 00333 00334 int landtileflagsearch( int argc, char **argv ) 00335 { 00336 00337 Core::open_uo_data_files( ); 00338 Core::read_uo_data( ); 00339 00340 if ( argc < 3 ) return 1; 00341 00342 unsigned int flags = strtoul( argv[2], NULL, 0 ); 00343 unsigned int notflags = 0; 00344 if ( argc >= 4 ) 00345 notflags = strtoul( argv[3], NULL, 0 ); 00346 00347 Core::USTRUCT_LAND_TILE landtile; 00348 00349 int i; 00350 for ( i = 0; i < 0x4000; i++ ) 00351 { 00352 unsigned short objtype = (unsigned short)i; 00353 readlandtile( objtype, &landtile ); 00354 if ( ( landtile.flags & flags ) == flags && 00355 ( ~landtile.flags & notflags ) == notflags ) 00356 { 00357 INFO_PRINT << "Land Tile: 0x" << fmt::hexu( objtype ) << "\n" 00358 << "\tflags: 0x" << fmt::hexu( landtile.flags ) << "\n" 00359 << "\t unk: 0x" << fmt::hexu( landtile.unk ) << "\n" 00360 << "\t name: " << landtile.name << "\n"; 00361 } 00362 } 00363 Core::clear_tiledata( ); 00364 return 0; 00365 } 00366 00367 int loschange( int /*argc*/, char** /*argv*/ ) 00368 { 00369 Core::USTRUCT_TILE tile; 00370 00371 Core::open_uo_data_files( ); 00372 Core::read_uo_data( ); 00373 00374 for ( int i = 0; i <= 0xFFFF; i++ ) 00375 { 00376 unsigned short objtype = (unsigned short)i; 00377 read_objinfo( objtype, tile ); 00378 00379 bool old_lostest = ( tile.flags & Core::USTRUCT_TILE::FLAG_WALKBLOCK ) != 0; 00380 00381 bool new_lostest = ( tile.flags & ( Core::USTRUCT_TILE::FLAG_WALKBLOCK | Core::USTRUCT_TILE::FLAG_NO_SHOOT ) ) != 0; 00382 00383 00384 if ( old_lostest != new_lostest ) 00385 { 00386 display_tileinfo( objtype, tile ); 00387 INFO_PRINT.Format( " Old LOS: %s\n New LOS: %s\n" ) << ( old_lostest ? "true" : "false" ) 00388 << ( new_lostest ? "true" : "false" ); 00389 00390 } 00391 00392 } 00393 Core::clear_tiledata( ); 00394 return 0; 00395 } 00396 00397 int print_verdata_info() 00398 { 00399 Core::open_uo_data_files( ); 00400 Core::read_uo_data( ); 00401 int num_version_records; 00402 Core::USTRUCT_VERSION vrec; 00403 00404 // FIXME: should read this once per run, per file. 00405 fseek( Core::verfile, 0, SEEK_SET ); 00406 fread( &num_version_records, sizeof num_version_records, 1, Core::verfile ); // ENDIAN-BROKEN 00407 00408 INFO_PRINT << "There are " << num_version_records << " version records.\n"; 00409 00410 int filecount[32]; 00411 int inv_filecount = 0; 00412 memset( filecount, 0, sizeof filecount ); 00413 00414 for ( int i = 0; i < num_version_records; i++ ) 00415 { 00416 fread( &vrec, sizeof vrec, 1, Core::verfile ); 00417 if ( vrec.file < 32 ) 00418 ++filecount[vrec.file]; 00419 else 00420 ++inv_filecount; 00421 } 00422 for ( int i = 0; i < 32; ++i ) 00423 { 00424 if ( filecount[i] ) 00425 INFO_PRINT << "File 0x" << fmt::hexu( i ) << ": " << filecount[i] << " versioned blocks.\n"; 00426 } 00427 if ( inv_filecount ) 00428 INFO_PRINT << inv_filecount << " invalid file indexes\n"; 00429 Core::clear_tiledata( ); 00430 return 0; 00431 } 00432 00433 int print_statics() 00434 { 00435 INFO_PRINT << "Reading UO data..\n"; 00436 Core::open_uo_data_files( ); 00437 Core::read_uo_data( ); 00438 int water = 0; 00439 int strange_water = 0; 00440 int cnt = 0; 00441 for ( u16 y = 30; y < 50; y++ ) 00442 { 00443 for ( u16 x = 5900; x < 5940; x++ ) 00444 { 00445 std::vector<Core::StaticRec> vec; 00446 Core::readallstatics( vec, x, y ); 00447 00448 if ( !vec.empty() ) 00449 { 00450 bool hdrshown = false; 00451 for ( const auto &elem : vec ) 00452 { 00453 int height = Core::tileheight( elem.graphic ); 00454 if ( elem.graphic >= 0x1796 && elem.graphic <= 0x17b2 ) 00455 { 00456 if ( elem.z == -5 && height == 0 ) 00457 water++; 00458 else 00459 strange_water++; 00460 continue; 00461 } 00462 if ( !hdrshown ) 00463 INFO_PRINT << x << "," << y << ":\n"; 00464 hdrshown = true; 00465 INFO_PRINT << "\tOBJT= 0x" << fmt::hexu( elem.graphic ) 00466 << " Z=" << int( elem.z ) << " HT=" << height 00467 << " FLAGS=0x" << fmt::hexu( Core::tile_uoflags( elem.graphic ) ) << "\n"; 00468 ++cnt; 00469 } 00470 } 00471 } 00472 } 00473 INFO_PRINT << cnt << " statics exist.\n" 00474 << water << " water tiles exist.\n" 00475 << strange_water << " strange water tiles exist.\n"; 00476 Core::clear_tiledata( ); 00477 return 0; 00478 } 00479 00480 00481 00482 void elimdupes( Core::StaticList& list ) 00483 { 00484 bool any = true; 00485 do 00486 { 00487 any = false; 00488 for ( unsigned i = 0; !any && ( i < list.size() ); ++i ) 00489 { 00490 for ( unsigned j = 0; !any && ( j < list.size() ); ++j ) 00491 { 00492 if ( i == j ) 00493 continue; 00494 if ( Core::tile_uoflags( list[i].graphic ) == Core::tile_uoflags( list[j].graphic ) && 00495 Core::tileheight( list[i].graphic ) == Core::tileheight( list[j].graphic ) && 00496 list[i].z == list[j].z ) 00497 { 00498 list[i] = list.back(); 00499 list.pop_back(); 00500 any = true; 00501 } 00502 } 00503 } 00504 } while ( any ); 00505 } 00506 00507 #if 0 00508 int test_new_statics() 00509 { 00510 INFO_PRINT << "Reading UO data..\n"; 00511 open_uo_data_files(); 00512 read_uo_data(); 00513 load_pol_static_files(); 00514 00515 for( unsigned x = 0; x < 6144; ++x ) 00516 { 00517 for( unsigned y = 0; y < 4096; ++y ) 00518 { 00519 StaticList list1, list2; 00520 readstatics( list1, x, y ); 00521 readstatics2( list2, x, y ); 00522 00523 for( unsigned i = 0; i < list1.size(); ++i ) 00524 { 00525 StaticRec& r1 = list1[i]; 00526 // see if this is represented 00527 // really should check that there aren't any extras, too! 00528 bool found = false; 00529 for( unsigned j = 0; j < list2.size(); ++j ) 00530 { 00531 StaticRec& r2 = list2[j]; 00532 if (tileheight(r1.graphic) == tileheight(r2.graphic) && 00533 r1.z == r2.z) 00534 { 00535 found = true; 00536 break; 00537 } 00538 } 00539 if (!found) 00540 { 00541 INFO_PRINT << "elem not found: x=" << x << ", y=" << y << ",i=" << i 00542 << ", r1.graphic=" << r1.graphic << ", r1.z=" << int(r1.z) 00543 << "\n"; 00544 INFO_PRINT << "list1:\n"; 00545 for( unsigned j = 0; j < list1.size(); ++j ) 00546 { 00547 INFO_PRINT << "gid=" << list1[j].graphic 00548 << " z=" << int(list1[j].z) 00549 << " ht=" << int(tileheight(list1[j].graphic)) 00550 << "\n"; 00551 } 00552 INFO_PRINT << "list2:\n"; 00553 for( unsigned j = 0; j < list2.size(); ++j ) 00554 { 00555 INFO_PRINT << "gid=" << list2[j].graphic 00556 << " z=" << int(list2[j].z) 00557 << " ht=" << int(tileheight(list2[j].graphic)) 00558 << "\n"; 00559 } 00560 } 00561 } 00562 } 00563 } 00564 clear_tiledata(); 00565 return 0; 00566 } 00567 #endif 00568 00569 int rawdump( int argc, char **argv ) 00570 { 00571 if ( argc != 5 ) 00572 return Usage( 1 ); 00573 00574 FILE *fp = fopen( argv[2], "rb" ); 00575 int hdrlen = atoi( argv[3] ); 00576 int reclen = atoi( argv[4] ); 00577 int recnum = 0; 00578 if ( !fp ) 00579 return 1; 00580 00581 if ( hdrlen ) 00582 { 00583 if ( fread( buffer, hdrlen, 1, fp ) != 1 ) 00584 { 00585 fclose( fp ); 00586 return 1; 00587 } 00588 fmt::Writer tmp; 00589 tmp << "Header:\n"; 00590 Clib::fdump( tmp, buffer, hdrlen ); 00591 INFO_PRINT << tmp.str() << "\n"; 00592 } 00593 00594 while ( fread( buffer, reclen, 1, fp ) == 1 ) 00595 { 00596 fmt::Writer tmp; 00597 tmp.Format( "Record {} (0x{:X}):\n" ) << recnum << recnum; 00598 Clib::fdump( tmp, buffer, reclen ); 00599 INFO_PRINT << tmp.str( ) << "\n"; 00600 00601 ++recnum; 00602 } 00603 INFO_PRINT << recnum << " records read.\n"; 00604 fclose( fp ); 00605 return 0; 00606 } 00607 00608 unsigned int read_ulong( std::istream& is ) 00609 { 00610 unsigned char a[4]; 00611 is.read( (char *)a, sizeof a ); 00612 return ( a[3] << 24 ) | ( a[2] << 16 ) | ( a[1] << 8 ) | a[0]; 00613 } 00614 00615 int print_sndlist( int /*argc*/, char** /*argv*/ ) 00616 { 00617 unsigned int offset; 00618 unsigned int length; 00619 unsigned int serial; 00620 char filename[15]; 00621 00622 std::string soundidxname = Plib::systemstate.config.uo_datafile_root + "soundidx.mul"; 00623 std::string soundname = Plib::systemstate.config.uo_datafile_root + "sound.mul"; 00624 std::ifstream soundidx(soundidxname.c_str(), std::ios::in | std::ios::binary); 00625 std::ifstream sound(soundname.c_str(), std::ios::in | std::ios::binary); 00626 int i; 00627 i = 0; 00628 while ( soundidx.good() ) 00629 { 00630 ++i; 00631 offset = read_ulong( soundidx ); 00632 length = read_ulong( soundidx ); 00633 serial = read_ulong( soundidx ); 00634 if ( !soundidx.good() ) 00635 break; 00636 00637 if ( offset == 0xFFffFFffLu ) 00638 continue; 00639 00640 sound.seekg(offset, std::ios::beg); 00641 if ( !sound.good() ) 00642 break; 00643 00644 sound.read( filename, sizeof filename ); 00645 INFO_PRINT << "0x" << fmt::hexu( i ) << ", 0x" << fmt::hexu( serial ) << ": " << filename << "\n" 00646 << "len " << length << "\n"; 00647 } 00648 return 0; 00649 } 00650 00651 void print_multihull( u16 i, Multi::MultiDef* multi ) 00652 { 00653 if ( multi->hull.empty() ) 00654 return; 00655 00656 Core::USTRUCT_TILE tile; 00657 read_objinfo( static_cast<u16>( i + ( Plib::systemstate.config.max_tile_id + 1 ) ), tile ); 00658 INFO_PRINT << "Multi 0x" << fmt::hexu (i + i + ( Plib::systemstate.config.max_tile_id + 1 ) ) 00659 << " -- " << tile.name << ":\n"; 00660 fmt::Writer tmp; 00661 for ( short y = multi->minry; y <= multi->maxry; ++y ) 00662 { 00663 for ( short x = multi->minrx; x <= multi->maxrx; ++x ) 00664 { 00665 unsigned short key = multi->getkey( x, y ); 00666 bool external = multi->hull2.count( key ) != 0; 00667 bool internal = multi->internal_hull2.count( key ) != 0; 00668 bool origin = ( x == 0 && y == 0 ); 00669 00670 if ( external && !internal ) 00671 tmp << 'H'; 00672 else if ( !external && internal ) 00673 tmp << 'i'; 00674 else if ( external && internal ) 00675 tmp << 'I'; 00676 else if ( origin ) 00677 tmp << '*'; 00678 else 00679 tmp << ' '; 00680 } 00681 tmp << "\n"; 00682 } 00683 tmp << "\n"; 00684 INFO_PRINT << tmp.str( ); 00685 } 00686 00687 void print_widedata( u16 i, Multi::MultiDef* multi ) 00688 { 00689 if ( multi->hull.empty() ) 00690 return; 00691 00692 Core::USTRUCT_TILE tile; 00693 read_objinfo( static_cast<u16>( i + ( Plib::systemstate.config.max_tile_id + 1 ) ), tile ); 00694 INFO_PRINT << "Multi 0x" << fmt::hexu( i + ( Plib::systemstate.config.max_tile_id + 1 ) ) 00695 << " -- " << tile.name << ":\n"; 00696 fmt::Writer tmp; 00697 for ( short y = multi->minry; y <= multi->maxry; ++y ) 00698 { 00699 for ( short x = multi->minrx; x <= multi->maxrx; ++x ) 00700 { 00701 const Multi::MULTI_ELEM* elem = multi->find_component( x, y ); 00702 if ( elem != NULL ) 00703 { 00704 tmp << "0x" << fmt::pad( fmt::hexu( elem->is_static ), 6 ) << ":"; 00705 } 00706 else 00707 { 00708 tmp << " " << ":"; 00709 } 00710 } 00711 tmp << "\n"; 00712 } 00713 tmp << "\n"; 00714 INFO_PRINT << tmp.str(); 00715 } 00716 00717 void print_multidata( u16 i, Multi::MultiDef* multi ) 00718 { 00719 if ( multi->hull.empty() ) 00720 return; 00721 00722 Core::USTRUCT_TILE tile; 00723 read_objinfo( static_cast<u16>( i + ( Plib::systemstate.config.max_tile_id + 1 ) ), tile ); 00724 INFO_PRINT << "Multi 0x" << fmt::hexu( i + ( Plib::systemstate.config.max_tile_id + 1 ) ) 00725 << " -- " << tile.name << ":\n"; 00726 fmt::Writer tmp; 00727 for ( const auto &_itr : multi->components ) 00728 { 00729 const Multi::MULTI_ELEM* elem = _itr.second; 00730 tmp << "0x" << fmt::hexu( elem->objtype) 00731 << " 0x" << fmt::hexu((int)elem->is_static) 00732 << ":" << elem->x << "," << elem->y << "," << elem->z << "\n"; 00733 } 00734 INFO_PRINT << tmp.str(); 00735 } 00736 00737 int print_multis( void ) 00738 { 00739 INFO_PRINT << "Reading UO data..\n"; 00740 Core::open_uo_data_files( ); 00741 Core::read_uo_data( ); 00742 Multi::read_multidefs(); 00743 00744 for ( u16 i = 0; i < 0x1000; ++i ) 00745 { 00746 if ( Multi::multidef_buffer.multidefs_by_multiid[i] ) 00747 { 00748 print_multihull( i, Multi::multidef_buffer.multidefs_by_multiid[i] ); 00749 print_multidata( i, Multi::multidef_buffer.multidefs_by_multiid[i] ); 00750 } 00751 } 00752 Core::clear_tiledata( ); 00753 return 0; 00754 00755 } 00756 00757 int z_histogram() 00758 { 00759 unsigned int zcount[256]; 00760 memset(zcount, 0, sizeof(zcount)); 00761 00762 INFO_PRINT << "Reading UO data..\n"; 00763 Core::open_uo_data_files( ); 00764 Core::read_uo_data( ); 00765 for ( u16 x = 0; x < 6143; ++x ) 00766 { 00767 INFO_PRINT << "."; 00768 for ( u16 y = 0; y < 4095; ++y ) 00769 { 00770 Core::USTRUCT_MAPINFO mi; 00771 short z; 00772 getmapinfo( x, y, &z, &mi ); 00773 assert( z >= Core::ZCOORD_MIN && z <= Core::ZCOORD_MAX ); 00774 ++zcount[z + 128]; 00775 } 00776 } 00777 INFO_PRINT << "\n"; 00778 for ( int i = 0; i < 256; ++i ) 00779 { 00780 if ( zcount[i] ) 00781 INFO_PRINT << i - 128 << ": " << zcount[i] << "\n"; 00782 } 00783 Core::clear_tiledata( ); 00784 return 0; 00785 } 00786 00787 int statics_histogram() 00788 { 00789 unsigned int counts[1000]; 00790 memset( counts, 0, sizeof counts ); 00791 INFO_PRINT << "Reading UO data..\n"; 00792 Core::open_uo_data_files( ); 00793 Core::read_uo_data( ); 00794 for ( u16 x = 0; x < 6143; x += 8 ) 00795 { 00796 INFO_PRINT << "."; 00797 for ( u16 y = 0; y < 4095; y += 8 ) 00798 { 00799 std::vector<Core::USTRUCT_STATIC> p; 00800 int count; 00801 00802 readstaticblock( &p, &count, x, y ); 00803 if ( count < 1000 ) 00804 ++counts[count]; 00805 else 00806 ERROR_PRINT << "doh: count=" << count << "\n"; 00807 } 00808 } 00809 INFO_PRINT << "\n"; 00810 for ( int i = 0; i < 1000; ++i ) 00811 { 00812 if ( counts[i] ) 00813 INFO_PRINT << i << ": " << counts[i] << "\n"; 00814 } 00815 Core::clear_tiledata( ); 00816 return 0; 00817 } 00818 00819 int write_polmap( const char* filename, unsigned short xbegin, unsigned short xend ) 00820 { 00821 INFO_PRINT << "Writing " << filename << "\n"; 00822 FILE* fp = fopen( filename, "wb" ); 00823 int num = xend + 1 - xbegin; 00824 for ( u16 xs = xbegin; xs < xend; xs += 8 ) 00825 { 00826 int percent = ( xs - xbegin ) * 100 / num; 00827 INFO_PRINT << "\r" << percent << "%"; 00828 for ( u16 ys = 0; ys < 4096; ys += 8 ) 00829 { 00830 short z; 00831 Core::USTRUCT_POL_MAPINFO_BLOCK blk; 00832 memset( &blk, 0, sizeof blk ); 00833 for ( u16 xi = 0; xi < 8; ++xi ) 00834 { 00835 for ( u16 yi = 0; yi < 8; ++yi ) 00836 { 00837 u16 x = xs + xi; 00838 u16 y = ys + yi; 00839 if ( x == 6143 ) x = 6142; 00840 if ( y == 4095 ) y = 4094; 00841 bool walkok = Core::groundheight( x, y, &z ); 00842 blk.z[xi][yi] = static_cast<signed char>( z ); 00843 if ( walkok ) 00844 blk.walkok[xi] |= ( 1 << yi ); 00845 } 00846 } 00847 fwrite( &blk, sizeof blk, 1, fp ); 00848 } 00849 } 00850 fclose( fp ); 00851 return 0; 00852 } 00853 00854 int write_polmap() 00855 { 00856 INFO_PRINT << "Reading UO data..\n"; 00857 Core::open_uo_data_files( ); 00858 Core::read_uo_data( ); 00859 write_polmap( "dngnmap0.pol", 5120, 6144 ); 00860 write_polmap( "map0.pol", 0, 6144 ); 00861 Core::clear_tiledata( ); 00862 return 0; 00863 } 00864 00865 int print_water_data() 00866 { 00867 Core::open_uo_data_files( ); 00868 Core::readwater( ); 00869 return 0; 00870 } 00871 00872 inline bool is_water( u16 objtype ) 00873 { 00874 return ( objtype >= 0x1796 && objtype <= 0x17b2 ); 00875 } 00876 bool has_water( u16 x, u16 y ) 00877 { 00878 Core::StaticList vec; 00879 vec.clear(); 00880 Core::readstatics( vec, x, y ); 00881 for ( const auto &rec : vec ) 00882 { 00883 if ( is_water( rec.graphic ) ) 00884 return true; 00885 } 00886 return false; 00887 } 00888 00889 int water_search( int /*argc*/, char** /*argv*/ ) 00890 { 00891 u16 wxl = 1420, wxh = 1480, wyl = 1760, wyh = 1780; 00892 Core::open_uo_data_files( ); 00893 for ( u16 y = wyl; y < wyh; y++ ) 00894 { 00895 for ( u16 x = wxl; x < wxh; x++ ) 00896 { 00897 if ( has_water( x, y ) ) 00898 INFO_PRINT << "W"; 00899 else 00900 INFO_PRINT << "."; 00901 } 00902 INFO_PRINT << "\n"; 00903 } 00904 INFO_PRINT << "\n"; 00905 return 0; 00906 } 00907 00908 int mapdump( int argc, char* argv[] ) 00909 { 00910 u16 wxl = 5485, wxh = 5500, wyl = 0, wyh = 30; 00911 00912 if ( argc >= 4 ) 00913 { 00914 wxl = wxh = static_cast<u16>( atoi( argv[2] ) ); 00915 wyl = wyh = static_cast<u16>( atoi( argv[3] ) ); 00916 } 00917 if ( argc >= 6 ) 00918 { 00919 wxh = static_cast<u16>( atoi( argv[4] ) ); 00920 wyh = static_cast<u16>( atoi( argv[5] ) ); 00921 } 00922 00923 Core::open_uo_data_files( ); 00924 Core::read_uo_data( ); 00925 00926 std::ofstream ofs( "mapdump.html" ); 00927 00928 ofs << "<table border=1 cellpadding=5 cellspacing=0>" << std::endl; 00929 ofs << "<tr><td> </td>"; 00930 for ( u16 x = wxl; x <= wxh; ++x ) 00931 { 00932 ofs << "<td align=center>" << x << "</td>"; 00933 } 00934 ofs << "</tr>" << std::endl; 00935 for ( u16 y = wyl; y <= wyh; ++y ) 00936 { 00937 ofs << "<tr><td valign=center>" << y << "</td>" << std::endl; 00938 for ( u16 x = wxl; x <= wxh; ++x ) 00939 { 00940 ofs << "<td align=left valign=top>"; 00941 short z; 00942 Core::USTRUCT_MAPINFO mi; 00943 safe_getmapinfo( x, y, &z, &mi ); 00944 Core::USTRUCT_LAND_TILE landtile; 00945 readlandtile( mi.landtile, &landtile ); 00946 ofs << "z=" << z << "<br>"; 00947 ofs << "landtile=" << Clib::hexint( mi.landtile ) << " " << landtile.name << "<br>"; 00948 ofs << " flags=" << Clib::hexint( landtile.flags ) << "<br>"; 00949 ofs << "mapz=" << (int)mi.z << "<br>"; 00950 00951 Core::StaticList statics; 00952 readallstatics( statics, x, y ); 00953 if ( !statics.empty() ) 00954 { 00955 ofs << "<table border=1 cellpadding=5 cellspacing=0>" << std::endl; 00956 ofs << "<tr><td>graphic</td><td>z</td><td>flags</td><td>ht</td>" << std::endl; 00957 for ( const auto &rec : statics ) 00958 { 00959 ofs << "<tr>"; 00960 ofs << "<td>" << Clib::hexint( rec.graphic ) << "</td>"; 00961 ofs << "<td>" << int( rec.z ) << "</td>"; 00962 ofs << "<td>" << Clib::hexint( rec.flags ) << "</td>"; 00963 ofs << "<td>" << int( rec.height ) << "</td>"; 00964 ofs << "</tr>" << std::endl; 00965 } 00966 ofs << "</table>" << std::endl; 00967 } 00968 ofs << "</td>" << std::endl; 00969 } 00970 ofs << "</tr>" << std::endl; 00971 } 00972 ofs << "</table>" << std::endl; 00973 Core::clear_tiledata( ); 00974 return 0; 00975 } 00976 00977 struct MapContour 00978 { 00979 signed char z[6144][4096]; 00980 }; 00981 00982 int contour( int /*argc*/, char** /*argv*/ ) 00983 { 00984 Core::open_uo_data_files( ); 00985 Core::read_uo_data( ); 00986 00987 auto mc = new MapContour; 00988 for ( u16 y = 0; y < 4095; ++y ) 00989 { 00990 for ( u16 x = 0; x < 6143; ++x ) 00991 { 00992 static Core::StaticList vec; 00993 00994 vec.clear(); 00995 00996 readstatics( vec, x, y ); 00997 00998 bool result; 00999 short newz; 01000 standheight( Core::MOVEMODE_LAND, vec, x, y, 127, 01001 &result, &newz ); 01002 if ( result ) 01003 { 01004 mc->z[x][y] = static_cast<signed char>( newz ); 01005 } 01006 else 01007 { 01008 mc->z[x][y] = 127; 01009 } 01010 } 01011 } 01012 01013 std::ofstream ofs("contour.dat", std::ios::trunc | std::ios::out | std::ios::binary); 01014 ofs.write( reinterpret_cast<const char*>( mc ), sizeof( MapContour ) ); 01015 Core::clear_tiledata( ); 01016 delete mc; 01017 return 0; 01018 } 01019 01020 int findlandtile( int /*argc*/, char **argv ) 01021 { 01022 int landtile = strtoul( argv[1], NULL, 0 ); 01023 Core::open_uo_data_files( ); 01024 Core::read_uo_data( ); 01025 01026 for ( u16 y = 0; y < 4095; ++y ) 01027 { 01028 for ( u16 x = 0; x < 6143; ++x ) 01029 { 01030 short z; 01031 Core::USTRUCT_MAPINFO mi; 01032 safe_getmapinfo( x, y, &z, &mi ); 01033 if ( mi.landtile == landtile ) 01034 { 01035 INFO_PRINT << x << "," << y << "," << (int)mi.z; 01036 if ( mi.z != z ) 01037 INFO_PRINT << " (" << z << ")"; 01038 INFO_PRINT << "\n"; 01039 } 01040 } 01041 } 01042 01043 Core::clear_tiledata( ); 01044 return 0; 01045 } 01046 01047 int findgraphic( int /*argc*/, char **argv ) 01048 { 01049 int graphic = strtoul( argv[1], NULL, 0 ); 01050 INFO_PRINT << "Searching map for statics with graphic=0x" << fmt::hexu( graphic ) << "\n"; 01051 01052 Core::open_uo_data_files( ); 01053 Core::read_uo_data( ); 01054 01055 for ( u16 y = 0; y < 4095; ++y ) 01056 { 01057 for ( u16 x = 0; x < 6143; ++x ) 01058 { 01059 Core::StaticList statics; 01060 readallstatics( statics, x, y ); 01061 for ( const auto &rec : statics ) 01062 { 01063 if ( rec.graphic == graphic ) 01064 { 01065 INFO_PRINT << x << "," << y << "," << rec.z << "\n"; 01066 } 01067 } 01068 } 01069 } 01070 Core::clear_tiledata( ); 01071 return 0; 01072 } 01073 01074 int findlandtileflags( int /*argc*/, char **argv ) 01075 { 01076 unsigned int flags = strtoul( argv[1], NULL, 0 ); 01077 Core::open_uo_data_files( ); 01078 Core::read_uo_data( ); 01079 01080 for ( u16 y = 0; y < 4095; ++y ) 01081 { 01082 for ( u16 x = 0; x < 6143; ++x ) 01083 { 01084 short z; 01085 Core::USTRUCT_MAPINFO mi; 01086 safe_getmapinfo( x, y, &z, &mi ); 01087 if ( Core::landtile_uoflags( mi.landtile ) & flags ) 01088 { 01089 INFO_PRINT << x << "," << y << "," << (int)mi.z 01090 << ": landtile 0x" << fmt::hexu( mi.landtile ) 01091 << ", flags 0x" << fmt::hexu( Core::landtile_uoflags( mi.landtile ) ) 01092 << "\n"; 01093 } 01094 } 01095 } 01096 01097 Core::clear_tiledata( ); 01098 return 0; 01099 } 01100 01101 int defragstatics( int argc, char **argv ) 01102 { 01103 const char* realm; 01104 if ( argc < 2 ) 01105 realm = "britannia"; 01106 else 01107 realm = argv[1]; 01108 01109 Plib::RealmDescriptor descriptor = Plib::RealmDescriptor::Load( realm ); 01110 01111 Core::uo_mapid = descriptor.uomapid; 01112 Core::uo_usedif = descriptor.uodif; 01113 Core::uo_map_width = static_cast<unsigned short>( descriptor.width ); 01114 Core::uo_map_height = static_cast<unsigned short>( descriptor.height ); 01115 01116 Core::open_uo_data_files( ); 01117 Core::read_uo_data( ); 01118 01119 std::string statidx = "staidx" + Clib::tostring(Core::uo_mapid) + ".mul"; 01120 std::string statics = "statics" + Clib::tostring(Core::uo_mapid) + ".mul"; 01121 Clib::RemoveFile( statidx ); 01122 Clib::RemoveFile( statics ); 01123 01124 FILE* fidx = fopen( statidx.c_str(), "wb" ); 01125 FILE* fmul = fopen( statics.c_str(), "wb" ); 01126 01127 int lastprogress = -1; 01128 for ( u16 x = 0; x < descriptor.width; x += Plib::STATICBLOCK_CHUNK ) 01129 { 01130 int progress = x * 100L / descriptor.width; 01131 if ( progress != lastprogress ) 01132 { 01133 INFO_PRINT << "\rRewriting statics files: " << progress << "%"; 01134 lastprogress = progress; 01135 } 01136 for ( u16 y = 0; y < descriptor.height; y += Plib::STATICBLOCK_CHUNK ) 01137 { 01138 std::vector<Core::USTRUCT_STATIC> pstat; 01139 int num; 01140 std::vector<Core::USTRUCT_STATIC> tilelist; 01141 readstaticblock( &pstat, &num, x, y ); 01142 if ( num>0 ) 01143 { 01144 int currwritepos = ftell( fmul ); 01145 for ( int i = 0; i < num; ++i ) 01146 { 01147 Core::USTRUCT_STATIC& tile = pstat[i]; 01148 if ( tile.graphic < 0x4000 ) 01149 { 01150 bool first = true; 01151 for ( const auto &stile : tilelist ) 01152 { 01153 if ( ( tile.graphic == stile.graphic ) 01154 && ( tile.x_offset == stile.x_offset ) 01155 && ( tile.y_offset == stile.y_offset ) 01156 && ( tile.z == stile.z ) 01157 && ( tile.hue == stile.hue ) ) 01158 { 01159 first = false; 01160 break; 01161 } 01162 } 01163 if ( first ) 01164 { 01165 Core::USTRUCT_STATIC newtile; 01166 newtile.graphic = tile.graphic; 01167 newtile.x_offset = tile.x_offset; 01168 newtile.y_offset = tile.y_offset; 01169 newtile.z = tile.z; 01170 newtile.hue = tile.hue; 01171 tilelist.push_back( newtile ); 01172 } 01173 } 01174 } 01175 Core::USTRUCT_IDX idx; 01176 idx.offset = ~0u; 01177 idx.length = ~0u; 01178 idx.unknown = ~0u; 01179 if ( !tilelist.empty() ) 01180 { 01181 idx.offset = currwritepos; 01182 for ( const auto &elem : tilelist ) 01183 { 01184 fwrite( &elem, sizeof( Core::USTRUCT_STATIC ), 1, fmul ); 01185 } 01186 currwritepos = ftell( fmul ) - currwritepos; 01187 idx.length = currwritepos; 01188 idx.unknown = 0; 01189 tilelist.clear(); 01190 } 01191 fwrite( &idx, sizeof idx, 1, fidx ); 01192 } 01193 else 01194 { 01195 Core::USTRUCT_IDX idx; 01196 idx.offset = ~0u; 01197 idx.length = ~0u; 01198 idx.unknown = ~0u; 01199 fwrite( &idx, sizeof idx, 1, fidx ); 01200 } 01201 } 01202 } 01203 01204 INFO_PRINT << "\rRewriting statics files: Complete\n"; 01205 fclose( fidx ); 01206 fclose( fmul ); 01207 return 0; 01208 } 01209 01210 int format_description( int argc, char **argv ) 01211 { 01212 std::string name = ""; 01213 for ( int i = 1; i < argc; ++i ) 01214 { 01215 name.append( argv[i] ); 01216 if ( i < ( argc - 1 ) ) 01217 name.append( " " ); 01218 } 01219 if ( name.length() == 0 ) 01220 return Usage( 1 ); 01221 for ( unsigned short amount = 1; amount <= 2; ++amount ) 01222 { 01223 const char *src = name.c_str(); 01224 01225 std::string desc; 01226 01227 if ( amount != 1 ) 01228 { 01229 char s[15]; 01230 sprintf( s, "%hu ", amount ); 01231 desc = s; 01232 } 01233 01234 int singular = ( amount == 1 ); 01235 int plural_handled = 0; 01236 int phase = 0; /* 0= first part, 1=plural part, 2=singular part, 3=rest */ 01237 char ch; 01238 while ( '\0' != ( ch = *src ) ) 01239 { 01240 if ( phase == 0 ) 01241 { 01242 if ( ch == '%' ) 01243 { 01244 plural_handled = 1; 01245 phase = 1; 01246 } 01247 else 01248 { 01249 desc += ch; 01250 } 01251 } 01252 else if ( phase == 1 ) 01253 { 01254 if ( ch == '%' ) 01255 phase = 3; 01256 else if ( ch == '/' ) 01257 phase = 2; 01258 else if ( !singular ) 01259 desc += ch; 01260 } 01261 else if ( phase == 2 ) 01262 { 01263 if ( ch == '%' ) 01264 phase = 3; 01265 else if ( singular ) 01266 desc += ch; 01267 } 01268 // if phase == 3 that means there are more words to come, 01269 // lets loop through them to support singular/plural stuff in more than just the first word of the desc. 01270 else 01271 { 01272 desc += ch; 01273 phase = 0; 01274 } 01275 ++src; 01276 } 01277 01278 if ( !singular && !plural_handled ) 01279 desc += 's'; 01280 01281 if ( amount == 1 ) 01282 INFO_PRINT << "Singular: " << desc << "\n"; 01283 else 01284 INFO_PRINT << "Plural: " << desc << "\n"; 01285 } 01286 return 0; 01287 } 01288 01289 int checkmultis() 01290 { 01291 FILE *multi_idx = Core::open_uo_file( "multi.idx" ); 01292 FILE *multi_mul = Core::open_uo_file( "multi.mul" ); 01293 if ( fseek( multi_idx, 0, SEEK_SET ) != 0 ) 01294 { 01295 fclose( multi_idx ); 01296 fclose( multi_mul ); 01297 INFO_PRINT << "Failed seek check\n"; 01298 return 0; 01299 } 01300 unsigned count = 0; 01301 unsigned warnings = 0; 01302 unsigned errors = 0; 01303 unsigned invisitems = 0; 01304 Core::USTRUCT_IDX idxrec; 01305 for ( int i = 0; fread( &idxrec, sizeof idxrec, 1, multi_idx ) == 1; ++i ) 01306 { 01307 if ( idxrec.offset == 0xFFffFFffLu ) 01308 continue; 01309 fseek( multi_mul, idxrec.offset, SEEK_SET ); 01310 Core::USTRUCT_MULTI_ELEMENT elem; 01311 fread( &elem, sizeof elem, 1, multi_mul ); 01312 if ( elem.x != 0 || elem.y != 0 || elem.z != 0 ) 01313 { 01314 INFO_PRINT << "ERROR: First tile not in center: " << elem.x << " " << elem.y << " " << elem.z << " (" << elem.flags << ") MultiID: 0x" << fmt::hexu( i ) << "\n"; 01315 ++errors; 01316 } 01317 else if ( elem.graphic == 0x0001 ) 01318 { 01319 ++invisitems; 01320 unsigned int itemcount = idxrec.length / sizeof elem; 01321 --itemcount; 01322 while ( itemcount-- ) 01323 { 01324 fread( &elem, sizeof elem, 1, multi_mul ); 01325 if ( elem.x == 0 && elem.y == 0 && elem.z == 0 && elem.graphic != 0x0001 && elem.flags ) 01326 { 01327 INFO_PRINT << "Warning: Found invis tile as center, but could use 0x" << fmt::hexu( elem.graphic ) << " at 0 0 0 MultiID: 0x" << fmt::hexu( i ) << "\n"; 01328 ++warnings; 01329 break; 01330 } 01331 } 01332 } 01333 ++count; 01334 } 01335 INFO_PRINT << "Checked Multis: " << count << " with invis center: " << invisitems << " Warnings: " << warnings << " Errors: " << errors << "\n"; 01336 fclose( multi_idx ); 01337 fclose( multi_mul ); 01338 return 1; 01339 } 01340 01341 } 01342 01343 int xmain( int argc, char* argv[] ) 01344 { 01345 Clib::StoreCmdArgs( argc, argv ); 01346 Clib::ConfigFile cf( "pol.cfg" ); 01347 Clib::ConfigElem elem; 01348 01349 cf.readraw( elem ); 01350 01351 Plib::systemstate.config.uo_datafile_root = elem.remove_string( "UoDataFileRoot" ); 01352 Plib::systemstate.config.uo_datafile_root = Clib::normalized_dir_form( Plib::systemstate.config.uo_datafile_root ); 01353 01354 unsigned short max_tile = elem.remove_ushort( "MaxTileID", UOBJ_DEFAULT_MAX ); 01355 01356 if ( max_tile != UOBJ_DEFAULT_MAX && max_tile != UOBJ_SA_MAX && max_tile != UOBJ_HSA_MAX ) 01357 Plib::systemstate.config.max_tile_id = UOBJ_DEFAULT_MAX; 01358 else 01359 Plib::systemstate.config.max_tile_id = max_tile; 01360 01361 if ( argc <= 1 ) 01362 return Uotool::Usage( 1 ); 01363 01364 if ( argv[1][0] == '/' || argv[1][1] == ':' ) 01365 { 01366 Plib::systemstate.config.uo_datafile_root = argv[1]; 01367 --argc; 01368 ++argv; 01369 } 01370 01371 if ( stricmp( argv[1], "tiledump" ) == 0 ) 01372 { 01373 return Uotool::tiledump( argc, argv ); 01374 } 01375 else if ( stricmp( argv[1], "vertile" ) == 0 ) 01376 { 01377 return Uotool::vertile( argc, argv ); 01378 } 01379 else if ( stricmp( argv[1], "verlandtile" ) == 0 ) 01380 { 01381 return Uotool::verlandtile( argc, argv ); 01382 } 01383 else if ( stricmp( argv[1], "landtilehist" ) == 0 ) 01384 { 01385 return Uotool::landtilehist( argc, argv ); 01386 } 01387 else if ( stricmp( argv[1], "flagsearch" ) == 0 ) 01388 { 01389 return Uotool::flagsearch( argc, argv ); 01390 } 01391 else if ( stricmp( argv[1], "landtileflagsearch" ) == 0 ) 01392 { 01393 return Uotool::landtileflagsearch( argc, argv ); 01394 } 01395 else if ( stricmp( argv[1], "loschange" ) == 0 ) 01396 { 01397 return Uotool::loschange( argc, argv ); 01398 } 01399 else if ( stricmp( argv[1], "rawdump" ) == 0 ) 01400 { 01401 return Uotool::rawdump( argc, argv ); 01402 } 01403 else if ( stricmp( argv[1], "ctable" ) == 0 ) 01404 { 01405 return Uotool::print_ctable(); 01406 } 01407 else if ( stricmp( argv[1], "sndlist" ) == 0 ) 01408 { 01409 return Uotool::print_sndlist( argc, argv ); 01410 } 01411 else if ( stricmp( argv[1], "statics" ) == 0 ) 01412 { 01413 return Uotool::print_statics(); 01414 } 01415 else if ( stricmp( argv[1], "verdata" ) == 0 ) 01416 { 01417 return Uotool::print_verdata_info(); 01418 } 01419 else if ( stricmp( argv[1], "multis" ) == 0 ) 01420 { 01421 return Uotool::print_multis(); 01422 } 01423 else if ( stricmp( argv[1], "water" ) == 0 ) 01424 { 01425 return Uotool::print_water_data(); 01426 } 01427 else if ( stricmp( argv[1], "newstatics" ) == 0 ) 01428 { 01429 return Core::write_pol_static_files( "main" ); 01430 } 01431 else if ( stricmp( argv[1], "staticsmax" ) == 0 ) 01432 { 01433 Core::open_uo_data_files(); 01434 Core::staticsmax(); 01435 return 0; 01436 } 01437 else if ( stricmp( argv[1], "watersearch" ) == 0 ) 01438 { 01439 return Uotool::water_search( argc, argv ); 01440 } 01441 else if ( stricmp( argv[1], "zhist" ) == 0 ) 01442 { 01443 return Uotool::z_histogram(); 01444 } 01445 else if ( stricmp( argv[1], "staticshist" ) == 0 ) 01446 { 01447 return Uotool::statics_histogram(); 01448 } 01449 else if ( stricmp( argv[1], "writedungmap" ) == 0 ) 01450 { 01451 return Uotool::write_polmap(); 01452 } 01453 else if ( stricmp( argv[1], "writekeys" ) == 0 ) 01454 { 01455 INFO_PRINT << "Keys written to current.key\n"; 01456 return 0; 01457 } 01458 else if ( stricmp( argv[1], "mapdump" ) == 0 ) 01459 { 01460 return Uotool::mapdump( argc, argv ); 01461 } 01462 else if ( stricmp( argv[1], "contour" ) == 0 ) 01463 { 01464 return Uotool::contour( argc, argv ); 01465 } 01466 else if ( stricmp( argv[1], "findlandtile" ) == 0 ) 01467 { 01468 return Uotool::findlandtile( argc - 1, argv + 1 ); 01469 } 01470 else if ( stricmp( argv[1], "findlandtileflags" ) == 0 ) 01471 { 01472 return Uotool::findlandtileflags( argc - 1, argv + 1 ); 01473 } 01474 else if ( stricmp( argv[1], "findgraphic" ) == 0 ) 01475 { 01476 return Uotool::findgraphic( argc - 1, argv + 1 ); 01477 } 01478 else if ( stricmp( argv[1], "defragstatics" ) == 0 ) 01479 { 01480 return Uotool::defragstatics( argc - 1, argv + 1 ); 01481 } 01482 else if ( stricmp( argv[1], "formatdesc" ) == 0 ) 01483 { 01484 return Uotool::format_description( argc - 1, argv + 1 ); 01485 } 01486 else if ( stricmp( argv[1], "checkmultis" ) == 0 ) 01487 { 01488 return Uotool::checkmultis(); 01489 } 01490 01491 return Uotool::Usage( 0 ); 01492 } 01493 }