Pol  Revision:794
pol/uofile03.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines