|
Pol
Revision:794
|
00001 /* 00002 History 00003 ======= 00004 2009/09/03 MuadDib: Relocation of multi related cpp/h 00005 00006 00007 Notes 00008 ======= 00009 00010 */ 00011 00012 #include "../clib/stl_inc.h" 00013 00014 #include <stdio.h> 00015 #include <string.h> 00016 00017 #include "../clib/strutil.h" 00018 00019 #include "charactr.h" 00020 #include "core.h" 00021 #include "item/item.h" 00022 #include "item/itemdesc.h" 00023 #include "polcfg.h" 00024 #include "udatfile.h" 00025 #include "ustruct.h" 00026 #include "uvars.h" 00027 #include "multi/multi.h" 00028 #include "uofile.h" 00029 #include "uofilei.h" 00030 #include "uworld.h" 00031 #include "zone.h" 00032 00033 //#define DEBUG_BOATS 00034 00035 namespace Pol { 00036 namespace Core { 00037 void readdynamics( StaticList& vec, unsigned short x, unsigned short y, Realm* realm, Items& ivec, bool doors_block ) 00038 { 00039 unsigned short wx, wy; 00040 w_convert2( x, y, wx, wy ); 00041 ZoneItems& witems = realm->zone[wx][wy].items; 00042 for ( ZoneItems::const_iterator itr = witems.begin(); itr != witems.end(); ++itr ) 00043 { 00044 Item *item = *itr; 00045 if ( ( item->x == x ) && ( item->y == y ) ) 00046 { 00047 if ( tile_flags( item->graphic ) & USTRUCT_TILE::FLAG_WALKBLOCK ) 00048 { 00049 if ( doors_block || ( ~tile_flags( item->graphic ) & USTRUCT_TILE::FLAG_DOOR ) ) 00050 vec.push_back( StaticRec( item->graphic, item->z ) ); 00051 } 00052 00053 // tile_flags(item->graphic) & USTRUCT_TILE::FLAG__UNKNOWN_01000000) 00054 if ( has_walkon_script( item->objtype_ ) ) 00055 { 00056 ivec.push_back( item ); 00057 } 00058 } 00059 } 00060 } 00061 00062 void readdynamics( const Character* chr, 00063 StaticList& vec, 00064 unsigned short x, unsigned short y, 00065 Items& ivec, bool doors_block ) 00066 { 00067 unsigned short wx, wy; 00068 w_convert2( x, y, wx, wy ); 00069 ZoneItems& witems = chr->realm->zone[wx][wy].items; 00070 for ( ZoneItems::const_iterator itr = witems.begin(); itr != witems.end(); ++itr ) 00071 { 00072 Item *item = *itr; 00073 if ( ( item->x == x ) && ( item->y == y ) ) 00074 { 00075 // cout << "dynamic found: " << hexint( item->objtype_ ) << " " << item->x << "," << item->y << endl; 00076 00077 if ( tile_flags( item->graphic ) & USTRUCT_TILE::FLAG_WALKBLOCK ) 00078 { 00079 if ( !chr->can_move( item ) && 00080 ( doors_block || ( ~tile_flags( item->graphic ) & USTRUCT_TILE::FLAG_DOOR ) ) ) 00081 { 00082 vec.push_back( StaticRec( item->graphic, item->z ) ); 00083 } 00084 } 00085 00086 // tile_flags(item->graphic) & USTRUCT_TILE::FLAG__UNKNOWN_01000000) 00087 if ( has_walkon_script( item->objtype_ ) ) 00088 { 00089 // cout << "dynamic has walkon script" << endl; 00090 ivec.push_back( item ); 00091 } 00092 } 00093 } 00094 } 00095 00096 typedef std::vector<UMulti*> MultiList; 00097 void readmultis( StaticList& vec, unsigned short x, unsigned short y, Realm* realm, MultiList& mvec ) 00098 { 00099 unsigned short wxL, wyL, wxH, wyH; 00100 w_convert2( x - 64, y - 64, wxL, wyL ); 00101 w_convert2( x + 64, y + 64, wxH, wyH ); 00102 00103 for ( unsigned short wx = wxL; wx <= wxH; ++wx ) 00104 { 00105 for ( unsigned short wy = wyL; wy <= wyH; ++wy ) 00106 { 00107 ZoneMultis& wmultis = realm->zone[wx][wy].multis; 00108 00109 for ( ZoneMultis::iterator itr = wmultis.begin(), end = wmultis.end(); itr != end; ++itr ) 00110 { 00111 UMulti* multi = *itr; 00112 const MultiDef& def = multi->multidef(); 00113 if ( def.readobjects( vec, int( x ) - multi->x, int( y ) - multi->y, multi->z ) ) 00114 { 00115 mvec.push_back( multi ); 00116 } 00117 } 00118 } 00119 } 00120 00121 00122 /* 00123 for( Multis::const_iterator itr = multis.begin(); itr != multis.end(); ++itr ) 00124 { 00125 UMulti* multi = *itr; 00126 const MultiDef& def = multi->multidef(); 00127 if (def.readobjects( vec, int(x) - multi->x, int(y) - multi->y, multi->z )) 00128 { 00129 mvec.push_back( multi ); 00130 } 00131 } 00132 */ 00133 } 00134 void readmultis( StaticList& vec, unsigned short x, unsigned short y, Realm* realm ) 00135 { 00136 unsigned short wxL, wyL, wxH, wyH; 00137 w_convert2( x - 64, y - 64, wxL, wyL ); 00138 w_convert2( x + 64, y + 64, wxH, wyH ); 00139 00140 for ( unsigned short wx = wxL; wx <= wxH; ++wx ) 00141 { 00142 for ( unsigned short wy = wyL; wy <= wyH; ++wy ) 00143 { 00144 ZoneMultis& wmultis = realm->zone[wx][wy].multis; 00145 00146 for ( ZoneMultis::iterator itr = wmultis.begin(), end = wmultis.end(); itr != end; ++itr ) 00147 { 00148 UMulti* multi = *itr; 00149 const MultiDef& def = multi->multidef(); 00150 def.readobjects( vec, int( x ) - multi->x, int( y ) - multi->y, multi->z ); 00151 } 00152 } 00153 } 00154 } 00155 00156 /* The supporting multi is the highest multi that is below or equal 00157 * to the Z-coord of the supported object. 00158 */ 00159 UMulti* uo_find_supporting_multi( MultiList& mvec, int z ) 00160 { 00161 UMulti* found = NULL; 00162 for ( MultiList::const_iterator itr = mvec.begin(), end = mvec.end(); itr != end; ++itr ) 00163 { 00164 UMulti* multi = ( *itr ); 00165 if ( multi->z <= z ) 00166 { 00167 if ( ( found == NULL ) || 00168 ( multi->z > found->z ) ) 00169 { 00170 found = multi; 00171 } 00172 } 00173 } 00174 return found; 00175 } 00176 00177 00178 // new Z given new X, Y, and old Z. 00179 bool uo_walkheight( int x, int y, int oldz, 00180 int* newz, 00181 UMulti** pmulti, Item** pwalkon, 00182 bool doors_block, 00183 MOVEMODE movemode ) 00184 { 00185 00186 if ( !VALID_WORLD_LOC( x, y, find_realm( string( "britannia" ) ) ) ) 00187 { 00188 return false; 00189 } 00190 00191 static StaticList vec; 00192 static MultiList mvec; 00193 static Items ivec; 00194 vec.clear(); 00195 mvec.clear(); 00196 ivec.clear(); 00197 00198 readdynamics( vec, x, y, ivec, true ); 00199 readmultis( vec, x, y, mvec ); 00200 readstatics( vec, x, y ); 00201 00202 bool result; 00203 standheight( movemode, vec, x, y, oldz, 00204 &result, newz ); 00205 if ( result ) 00206 { 00207 if ( !mvec.empty() ) 00208 { 00209 *pmulti = uo_find_supporting_multi( mvec, *newz ); 00210 } 00211 else 00212 { 00213 *pmulti = NULL; 00214 } 00215 if ( !ivec.empty() ) 00216 { 00217 *pwalkon = find_walkon_item( ivec, *newz ); 00218 } 00219 else 00220 { 00221 *pwalkon = NULL; 00222 } 00223 00224 } 00225 return result; 00226 } 00227 00228 // new Z given new X, Y, and old Z. 00229 bool uo_walkheight( const Character* chr, 00230 int x, int y, int oldz, 00231 int* newz, 00232 UMulti** pmulti, Item** pwalkon ) 00233 { 00234 00235 if ( !VALID_WORLD_LOC( x, y, chr->realm ) ) 00236 { 00237 return false; 00238 } 00239 00240 00241 static StaticList vec; 00242 static MultiList mvec; 00243 static Items ivec; 00244 vec.clear(); 00245 mvec.clear(); 00246 ivec.clear(); 00247 00248 readdynamics( chr, vec, x, y, ivec, chr->doors_block() ); 00249 readmultis( vec, x, y, mvec ); 00250 readstatics( vec, x, y ); 00251 00252 bool result; 00253 standheight( chr->movemode, vec, x, y, oldz, &result, newz ); 00254 if ( result ) 00255 { 00256 if ( !mvec.empty() ) 00257 { 00258 *pmulti = uo_find_supporting_multi( mvec, *newz ); 00259 } 00260 else 00261 { 00262 *pmulti = NULL; 00263 } 00264 if ( !ivec.empty() ) 00265 { 00266 //cout << "walkon vec isn't empty" << endl; 00267 *pwalkon = find_walkon_item( ivec, *newz ); 00268 //if (*pwalkon) 00269 // cout << "found a walkon" << endl; 00270 } 00271 else 00272 { 00273 *pwalkon = NULL; 00274 } 00275 00276 } 00277 //cout << "walkheight result: " << result << endl; 00278 return result; 00279 } 00280 00281 // new Z given new X, Y, and old Z. 00282 bool uo_dropheight( int x, int y, int oldz, 00283 int* newz, 00284 UMulti** pmulti ) 00285 { 00286 00287 if ( !VALID_WORLD_LOC( x, y, find_realm( string( "britannia" ) ) ) ) 00288 { 00289 return false; 00290 } 00291 00292 static StaticList vec; 00293 static MultiList mvec; 00294 static Items ivec; 00295 vec.clear(); 00296 mvec.clear(); 00297 ivec.clear(); 00298 00299 readdynamics( vec, x, y, ivec, true ); 00300 readmultis( vec, x, y, mvec ); 00301 readstatics( vec, x, y ); 00302 00303 bool result = groundheight( x, y, newz ); 00304 00305 statics_dropheight( vec, x, y, oldz, &result, newz ); 00306 if ( result ) 00307 { 00308 if ( !mvec.empty() ) 00309 { 00310 *pmulti = uo_find_supporting_multi( mvec, *newz ); 00311 } 00312 else 00313 { 00314 *pmulti = NULL; 00315 } 00316 00317 } 00318 return result; 00319 } 00320 00321 00322 bool uo_lowest_standheight( int x, int y, int* z ) 00323 { 00324 static StaticList vec; 00325 vec.clear(); 00326 readstatics( vec, x, y ); 00327 USTRUCT_MAPINFO mi; 00328 getmapinfo( x, y, z, &mi ); 00329 bool res = true; 00330 standheight( MOVEMODE_LAND, vec, x, y, *z, &res, z ); 00331 return res; 00332 } 00333 00334 UMulti* uo_find_supporting_multi( unsigned short x, unsigned short y, int z ) 00335 { 00336 if ( !VALID_WORLD_LOC( x, y, find_realm( string( "britannia" ) ) ) ) 00337 { 00338 return NULL; 00339 } 00340 00341 static StaticList vec; 00342 static MultiList mvec; 00343 vec.clear(); 00344 mvec.clear(); 00345 readmultis( vec, x, y, mvec ); 00346 00347 if ( !mvec.empty() ) 00348 { 00349 return uo_find_supporting_multi( mvec, z ); 00350 } 00351 else 00352 { 00353 return NULL; 00354 } 00355 } 00356 00357 bool uo_passable( unsigned short ax, unsigned short ay ) 00358 { 00359 /* 00360 * Assume if the map says water's here, there won't be statics on top. 00361 * Note, it _may_ be possible, if the map says there's water at the center, 00362 * to assume there's water for the entire hull. 00363 * Also note this early continue precludes dynamics blocking... 00364 */ 00365 USTRUCT_MAPINFO mi; 00366 rawmapinfo( ax, ay, &mi ); 00367 if ( mi.landtile >= USTRUCT_MAPINFO::WATER__LOWEST && mi.landtile <= USTRUCT_MAPINFO::WATER__HIGHEST ) 00368 return true; 00369 // possible early 'return false' if level 00370 00371 00372 /* 00373 * Last chance: does statics0.mul have a water tile here, and no other blocking statics? 00374 */ 00375 static StaticList vec; 00376 vec.clear(); 00377 readstatics( vec, ax, ay ); // FIXME is WALKBLOCK right here? 00378 // readnonboatdynamics 00379 bool onwater = false; 00380 for ( StaticList::const_iterator itr = vec.begin(), end = vec.end(); itr != end; ++itr ) 00381 { 00382 const StaticRec& srec = *itr; 00383 // if (tile_flags( srec.graphic ) & USTRUCT_TILE::FLAG_LIQUID) 00384 00385 if ( srec.graphic >= 0x1796 && srec.graphic <= 0x17B2 ) // FIXME hardcoded 00386 // if (tile_flags( srec.graphic ) & USTRUCT_TILE::FLAG_PASSABLE_WATER == 00387 // USTRUCT_TILE::FLAG_PASSABLE_WATER) 00388 { 00389 onwater = true; 00390 } 00391 else 00392 { 00393 #ifdef DEBUG_BOATS 00394 INFO_PRINT << "Location at " << ax << "," << ay << " has a non-water static: 0x" << fmt::hexu( srec.graphic ) << "\n"; 00395 #endif 00396 return false; 00397 } 00398 } 00399 if ( !onwater ) 00400 { 00401 #ifdef DEBUG_BOATS 00402 INFO_PRINT << "Location at " << ax << "," << ay << " has no water static\n"; 00403 #endif 00404 return false; 00405 } 00406 00407 /* 00408 * None of the above fired, so it's passable 00409 */ 00410 return true; 00411 } 00412 } 00413 }